2012-10-27 11 views
5

GetCurrentThreadId() è stato deprecato e MSDN afferma che ManagedThreadId lo sostituisce.Sostituzione AppDomain.GetCurrentThreadId(); con ManagedThreadId

Tuttavia, sto ottenendo risultati diversi e quest'ultimo causa un'eccezione nel mio codice. Il mio codice è adattato da this post.

 public static void SetThreadProcessorAffinity(params byte[] cpus) 
     { 
      if (cpus == null) 
      { 
       throw new ArgumentNullException("cpus"); 
      } 

      if (cpus.Length == 0) 
      { 
       throw new ArgumentException(@"You must specify at least one CPU.", "cpus"); 
      } 

      // Supports up to 64 processors 
      long cpuMask = 0; 
      byte max = (byte)Math.Min(Environment.ProcessorCount, 64); 

      foreach (byte cpu in cpus) 
      { 
       if (cpu >= max) 
       { 
        throw new ArgumentException(@"Invalid CPU number."); 
       } 

       cpuMask |= 1L << cpu; 
      } 

      // Ensure managed thread is linked to OS thread; does nothing on default host in current .NET versions 
      Thread.BeginThreadAffinity(); 

#pragma warning disable 618 
      // The call to BeginThreadAffinity guarantees stable results for GetCurrentThreadId, 
      // so we ignore the obsolete warning. 
      int osThreadId = AppDomain.GetCurrentThreadId(); 
      osThreadId = Thread.CurrentThread.ManagedThreadId;// NOT THE SAME VALUE 
#pragma warning restore 618 

      // Find the ProcessThread for this thread 
      ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>() 
       .Where(t => t.Id == osThreadId).Single(); 

      // Set the thread's processor affinity 
      thread.ProcessorAffinity = new IntPtr(cpuMask); 
     } 

Posso vedere il problema è che si ottiene l'ID di processo del thread mentre l'altro ottiene l'ID di processo dell'app.

Come posso far funzionare tutto questo senza utilizzare il metodo deprecato? Lo stack originale   dichiara che l'overflow utilizza P/Invoke, ma non so come, e questo non è ciò che afferma MSDN.

risposta

14

No, ManagedThreadId non ha alcuna relazione con l'ID filo del sistema operativo. Il CLR calcola semplicemente i thread, a partire da 1. Questo è un effetto collaterale abbastanza tragico di un progetto nel gruppo SQL Server che ha cercato di emulare i thread .NET con le fibre. Il progetto fu abbandonato, non riuscirono a farlo abbastanza stabile. Purtroppo la mappatura dell'ID del thread è rimasta come era quando .NET 2.0 è stato spedito. Tecnicamente, la funzione è ancora disponibile per gli host CLR personalizzati per implementare i thread nel modo desiderato, non sono a conoscenza di alcuna implementazione mainstream. L'errore del gruppo SQL Server è una bandiera rossa gigante.

L'unico modo per ignorare l'avviso di obsoletion consiste nel pinvoke GetCurrentThreadId(). Il link ti porta a fare la dichiarazione pinvoke corretta.

+0

Per curiosità, presumo che la chiamata kernell32.dll non funzioni con Mono? – IamIC

+2

"#pragma warning disable 0618" nel file di origine in cui si utilizza GetCurrentThreadId sopprimerà l'avviso. – Neutrino

+1

Per quanto riguarda il commento di Neutrino, la disattivazione di [avviso CS0618] (http://msdn.microsoft.com/en-us/library/x5ye6x1e.aspx) disabiliterà tutti gli avvisi obsoleti in quel file. Questo può essere localizzato avvolgendo il codice di destinazione in '#pragma warning disable 0618' ... il tuo codice qui ...' #pragma warning restore 0618'. ['#pragma warning' reference here] (http://msdn.microsoft.com/en-us/library/441722ys.aspx) – cod3monk3y