2010-11-16 12 views
38
  1. ¿Por qué aparece este mensaje de error? "WaitAll para múltiples identificadores en un subproceso STA no es compatible".
  2. ¿Debo usar [MTAThreadAttribute] attribut? Actualización: ¡No funciona con aplicaciones WPF!

Nota: Error en la línea WaitHandle.WaitAll (doneEvents); Estoy usando un proyecto WPF estándar.WaitAll para múltiples identificadores en un hilo STA no es compatible

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 de la aplicación principal a MTAThreadAttribute. Se producirá el siguiente error:

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

+0

Se da cuenta de que la aplicación va a congelar por completo hasta que los indexadores se hacen? – liggett78

+0

¡Sí! Yo sé eso. Pero tal como es, no se ejecuta. –

+1

http://stackoverflow.com/questions/3784510/notsupportedexception-on-waithandle-waitall –

Respuesta

17

¿Qué pasa con el uso de las tareas para hacer su rosca para usted.

http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx

var task1 = Task.Factory.StartNew(() => DoSomeWork()); 
var task2 = Task.Factory.StartNew(() => DoSomeWork()); 
var task3 = Task.Factory.StartNew(() => DoSomeWork()); 
Task.WaitAll(task1, task2, task3); 
+4

Es .NET Framework 4. Así que tengo que actualizar el proyecto. Parece ser un mejor enfoque pensado! –

+2

'Task.Run ((= = DoSomeWork())' es una mejor alternativa – gldraphael

8

Use uno ManualResetEvent y aguarde. También mantenga una variable TaskCount que se establece en la cantidad de hilos de trabajo que inicia, use Interlocked.Decrement en el código del hilo del trabajador 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(); 
+0

Gracias parece ser la única solución ya que WaitAll (..) no funciona. –

+0

Sí, eso funcionaría. Solo asegúrese de tratar el hilo principal como si fuera un elemento de trabajo e inicialice 'taskCount = 1' y haga el' Decrement' y 'Set' al final del ciclo' for'. –

6

Me refactorizar el código para utilizar 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!"); 
} 
+0

NB: .NET 4 solo –

45

Actualmente utilizo lo siguiente para reemplazar WaitHandle.WaitAll (doneEvents);

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

¿hay alguna desventaja en el uso de esta alternativa? – invertigo

+3

No he visto ninguno, pero recomendaría usar Task para el nuevo código – Calimero100582

0

uso 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); 
+1

CompletedEvent es del tipo System.Threading.AutoResetEvent – CSharper

+0

-1 Mientras más limpio, para mí esto no es lo suficientemente diferente de http://stackoverflow.com/a/4194938/11635 –

Cuestiones relacionadas