2009-06-01 6 views
13

So come ottenere l'utilizzo della CPU e l'utilizzo della memoria per un processo, ma mi chiedevo come ottenerlo a livello di thread. Se la soluzione migliore è fare un P-Invocation, allora va bene anche questo.Come posso ottenere l'utilizzo della CPU e/o l'utilizzo della RAM di un * THREAD * in C# (codice gestito)?

Esempio di quello che mi serve:

Thread myThread = Thread.CurrentThread; 

// some time later in some other function... 

Console.WriteLine(GetThreadSpecificCpuUsage(myThread)); 

risposta

7

Non è possibile ottenere l'utilizzo della memoria per thread perché la memoria è condivisa tra tutte le discussioni in un processo . Come saprebbe il sistema operativo se hai allocato la memoria in un thread e l'hai usata in un altro. E cosa significherebbe?

+0

C'è spazio per il thread locale. – CesarGon

+0

Ma in genere TLS viene utilizzato solo per contenere un riferimento a un oggetto nella memoria condivisa. – erikkallen

+0

Non è il sistema operativo quello che deve determinare l'utilizzo di un thread, è il framework stesso. –

10

Come detto, l'uso della memoria non può essere risolta dal momento che è un attributo del processo nel suo insieme, ma l'uso della CPU:

Process p = Process.GetCurrentProcess(); // getting current running process of the app 
foreach (ProcessThread pt in p.Threads) 
{ 
    // use pt.Id/pt.TotalProcessorTime/pt.UserProcessorTime/pt.PrivilegedProcessorTime 
} 
1

Ecco un semplice programma che lancia 5 fili che consumano diverse quantità di CPU e quindi corrisponde a quale thread gestito sta consumando la quantità di CPU.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Threading; 

class Program 
{ 
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] 
public static extern Int32 GetCurrentWin32ThreadId(); 

static void Main(string[] args) 
{ 
    Dictionary<int, Thread> threads = new Dictionary<int, Thread>(); 

    // Launch the threads 
    for (int i = 0; i < 5; i++) 
    { 
     Thread cpuThread = new Thread((start) => 
     { 
      lock (threads) 
      { 
       threads.Add(GetCurrentWin32ThreadId(), Thread.CurrentThread); 
      } 

      ConsumeCPU(20 * (int)start); 
     }); 
     cpuThread.Name = "T" + i; 
     cpuThread.Start(i); 
    } 

    // Every second wake up and see how much CPU each thread is using. 
    Thread monitoringThread = new Thread(() => 
     { 
      Stopwatch watch = new Stopwatch(); 
      watch.Start(); 

      while (true) 
      { 
       Thread.Sleep(1000); 
       Console.Write("\r"); 

       double totalTime = ((double)watch.ElapsedMilliseconds); 
       if (totalTime > 0) 
       { 
        Process p = Process.GetCurrentProcess(); 
        foreach (ProcessThread pt in p.Threads) 
        { 
         Thread managedThread; 
         if (threads.TryGetValue(pt.Id, out managedThread)) 
         { 
          double percent = (pt.TotalProcessorTime.TotalMilliseconds/totalTime); 
          Console.Write("{0}-{1:0.00} ", managedThread.Name, percent); 
         } 
        } 
       } 
      } 
     }); 
    monitoringThread.Start(); 
} 


// Helper function that generates a percentage of CPU usage 
public static void ConsumeCPU(int percentage) 
{ 
    Stopwatch watch = new Stopwatch(); 
    watch.Start(); 
    while (true) 
    { 
     if (watch.ElapsedMilliseconds > percentage) 
     { 
      Thread.Sleep(100 - percentage); 
      watch.Reset(); 
      watch.Start(); 
     } 
    } 
} 
} 

Si noti che è possibile che CLR cambi il thread nativo in esecuzione nel thread gestito. Tuttavia, in pratica non sono sicuro di quanto spesso ciò avvenga.