2009-02-01 19 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); 
      } 
     } 
    } 
} 

¿Cómo uso ThreadPool clase en sustitución del hilo & monitor?Cómo utilizar la clase ThreadPool

+0

Hola huda ¿Puedes formatear esto un poco mejor? –

+0

recuerde proteger el interior de sus métodos de trabajo con try-catch porque las excepciones en los subprocesos de trabajo simplemente matan silenciosamente el hilo –

Respuesta

1

Usted debe mirar en ThreadPool.QueueUserWorkItem(). Se necesita un delegado que se ejecuta en la cadena de subprocesos, pasando un objeto de estado.

decir

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

No se deje confundir por Control.BeginInvoke(). Esto coordinará la llamada al hilo que creó el control, para evitar el problema donde las llamadas entre hilos actualizan los controles. Si desea un multihilo simple en un formulario de Windows, busque en el 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

Hay varias formas de utilizar el grupo de subprocesos. Para su tarea, debe mirar lo siguiente.

  • Si solo necesita ejecutar una tarea de la manera más fácil es usar QueueUserWorkItem, que simplemente necesita un delegado para ejecutarse. La desventaja es que tiene poco control sobre el trabajo. El delegado no puede devolver un valor, y usted no sabe cuándo se completa la ejecución.
  • Si quiere un poco más de control, puede usar la interfaz BeginInvoke/EndInvoke de los delegados. Esto programa el código para ejecutarse en un hilo del grupo de subprocesos. Puede consultar el estado mediante el identificador IAsyncResult devuelto por BeginInvoke, y puede obtener el resultado (así como cualquier excepción en el hilo del trabajador) a través del EndInvoke.

Para utilizar el Enter/Exit en Monitor correctamente, usted tiene que asegurarse de que siempre se llama Exit. Por lo tanto, debe realizar su llamada Exit en un bloque finally.

Sin embargo, si no es necesario proporcionar un valor de tiempo de espera para Enter, que sería mucho mejor simplemente usando la palabra clave lock, que compila en un conjunto adecuado de Enter y Exit llamadas.

+0

Puede usar un AutoResetEvent o ManualResetEvent para determinar cuándo se completa la ejecución (como en la respuesta de pablito). – Cocowalla

0

No use el grupo de subprocesos para nada más que las cosas más simples. De hecho, es extremadamente peligroso obtener un bloqueo en un hilo de grupo de subprocesos. Sin embargo, puede usar de forma segura las API entrelazadas.

Cuestiones relacionadas