2009-02-01 13 views
5
namespace ThPool 
{ 
    class Program 
    { 
     private static long val = 0; 
     private static string obj = string.Empty; 

     static void Main(string[] args) 
     { 
      Thread objThread1 = new Thread(new ThreadStart(IncrementValue)); 
      objThread1.Start(); 
      Thread objThread2 = new Thread(new ThreadStart(IncrementValue)); 
      objThread2.Start(); 
      objThread1.Join(); 
      objThread2.Join(); 

      Console.WriteLine("val=" + val + " however it should be " + (10000000 + 10000000)); 

      Console.ReadLine(); 
     } 

     private static void IncrementValue() 
     { 
      for (int i = 0; i < 10000000; i++) 
      { 
       Monitor.Enter(obj); 
       val++; 
       Monitor.Exit(obj); 
      } 
     } 
    } 
} 

Come posso usare ThreadPool classe in sostituzione del filo & monitor?Come utilizzare classe ThreadPool

+0

Ciao huda Puoi per favore formattare questo un po 'meglio? –

+0

ricorda di proteggere gli interni dei metodi di lavoro con try-catch perché le eccezioni nei thread di lavoro uccidono silenziosamente la discussione –

risposta

1

Si dovrebbe guardare in ThreadPool.QueueUserWorkItem(). Prende un delegato che viene eseguito sul thread del threadpool, passando in un oggetto di stato.

cioè

string fullname = "Neil Barnwell"; 
ThreadPool.QueueUserWorkItem(state => 
{ 
    Console.WriteLine("Hello, " + (string)state); 
}, fullname); 

non è confuso da Control.BeginInvoke(). Ciò effettuerà il marshalling della chiamata al thread che ha creato il controllo, per impedire il problema in cui le chiamate cross-thread aggiornano i controlli. Se si desidera la semplice multi-threading su un modulo di Windows, quindi esaminare il BackgroundWorker.

2
EventWaitHandle[] waitHandles = new EventWaitHandle[2]; 


for(int i = 0; i < 2; i++) 
{ 
    waitHandles[i] = new AutoResetEvent(false); 
    ThreadPool.QueueUserWorkItem(state => 
    { 
     EventWaitHandle handle = state as EventWaitHandle; 
     for(int j = 0; j < 10000000; j++) 
     { 
      Interlocked.Increment(ref val); //instead of Monitor 
     } 
     handle.Set(); 
    }, waitHandles[i]); 
} 

WaitHandle.WaitAll(waitHandles); 
Console.WriteLine("val=" + val + " however it should be " + (10000000 + 10000000)); 
4

Ci sono un paio di modi per utilizzare il pool di thread. Per il tuo compito, dovresti guardare quanto segue.

  • Se hai solo bisogno di un compito per eseguire il modo più semplice è quello di utilizzare QueueUserWorkItem, che richiede semplicemente un delegato per l'esecuzione. Lo svantaggio è che hai poco controllo sul lavoro. Il delegato non può restituire un valore e non si sa quando la corsa è completata.
  • Se si desidera un po 'più di controllo, è possibile utilizzare l'interfaccia BeginInvoke/EndInvoke dei delegati. Ciò pianifica il codice per l'esecuzione in un thread del pool di thread. È possibile interrogare lo stato tramite l'handle IAsyncResult restituito da BeginInvoke ed è possibile ottenere il risultato (oltre a qualsiasi eccezione sul thread di lavoro) tramite EndInvoke.

Per utilizzare il Enter/Exit su Monitor correttamente, è necessario assicurarsi che Exit viene sempre chiamato. Pertanto, è necessario effettuare la chiamata Exit in un blocco finally.

Tuttavia, se non è necessario fornire un valore di timeout per Enter, si sarebbe molto meglio solo utilizzando la parola chiave lock, che compila in una vera e propria serie di Enter e Exit chiamate.

+0

Puoi utilizzare un AutoResetEvent o ManualResetEvent per determinare quando la corsa è stata completata (come nella risposta di pablito). – Cocowalla

0

Non utilizzare il pool di thread per scopi diversi da quelli più semplici. In effetti è estremamente pericoloso acquisire un blocco su un thread pool di thread. Tuttavia puoi tranquillamente usare le API interbloccate.

Problemi correlati