waitcallback thread practices example ejemplo best c# multithreading threadpool

practices - threadpool.queueuserworkitem example c#



WaitAll para varios manejadores en un hilo STA no es compatible (5)

  1. ¿Por qué recibo este mensaje de error? "WaitAll para varios manejadores en un subproceso STA no es compatible".
  2. ¿Debo usar el atributo [MTAThreadAttribute]? Actualización: ¡ No funciona con aplicaciones WPF!

Nota: el error está en la línea WaitHandle.WaitAll (doneEvents); Estoy usando un proyecto estándar de WPF .

private void Search() { const int CPUs = 2; var doneEvents = new ManualResetEvent[CPUs]; // Configure and launch threads using ThreadPool: for (int i = 0; i < CPUs; i++) { doneEvents[i] = new ManualResetEvent(false); var f = new Indexer(Paths[i], doneEvents[i]); ThreadPool.QueueUserWorkItem(f.WaitCallBack, i); } // Wait for all threads in pool WaitHandle.WaitAll(doneEvents); Debug.WriteLine("Search completed!"); }

Actualización: ¡ La siguiente solución no funciona para aplicaciones WPF! No es posible cambiar el atributo principal de la aplicación a MTAThreadAttribute. Resultará en el siguiente error:

Error: "WaitAll para múltiples manejadores en un subproceso STA no es compatible".



En realidad, uso lo siguiente para reemplazar WaitHandle.WaitAll (doneEvents);

foreach (var e in doneEvents) e.WaitOne();


Me gustaría refactorizar su código para usar la clase CountdownEvent lugar.

private void Search() { const int CPUs = 2; var done = new CountdownEvent(1); // Configure and launch threads using ThreadPool: for (int i = 0; i < CPUs; i++) { done.AddCount(); var f = new Indexer(Paths[i], doneEvents[i]); ThreadPool.QueueUserWorkItem( (state) => { try { f.WaitCallBack(state); } finally { done.Signal(); } }, i); } // Wait for all threads in pool done.Signal(); done.Wait(); Debug.WriteLine("Search completed!"); }


Use un ManualResetEvent y espere en él. También mantenga una variable TaskCount que se establece en el número de subprocesos de trabajo que inicia, use Interlocked.Decrement en el código de subproceso de trabajo como la última acción del trabajador y señale el evento si el contador llega a cero, por ejemplo

// other worker actions... if (Interlocked.Decrement(ref taskCount) == 0) doneEvent.Set();


usa algo como esto:

foreach (ITask Task in Tasks) { Task.WaitHandle = CompletedEvent; new Thread(Task.Run).Start(); } int TasksCount = Tasks.Count; for (int i = 0; i < TasksCount; i++) CompletedEvent.WaitOne(); if (AllCompleted != null) AllCompleted(this, EventArgs.Empty);