WaitAll per più handle su un thread STA non è supportato

  1. Perché ricevo questo messaggio di errore? “WaitAll per più handle su un thread STA non è supportato.”
  2. Dovrei usare [MTAThreadAttribute] attribut? Aggiornamento: non funziona con le applicazioni WPF!

Nota: l’errore è sulla riga WaitHandle.WaitAll (doneEvents); Sto usando un progetto WPF standard.

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!"); } 

Aggiornamento: la seguente soluzione non funziona per le applicazioni WPF! Non è ansible modificare l’attributo dell’applicazione principale in MTAThreadAttribute. Risulterà il seguente errore:

Errore: “WaitAll per più handle su un thread STA non è supportato.”

Che ne pensi di utilizzare i compiti per fare il tuo threading per te.

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); 

In realtà io uso il seguente per sostituire WaitHandle.WaitAll (doneEvents);

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

Utilizzare un ManualResetEvent e attendere su di esso. Mantenere anche una variabile TaskCount impostata sul numero di thread di lavoro avviati, utilizzare Interlocked.Decrement nel codice del thread worker come ultima azione dell’operatore e segnalare l’evento se il contatore raggiunge lo zero, ad esempio

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

Riforterà il tuo codice per utilizzare invece la class CountdownEvent .

 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!"); } 

usa qualcosa come questo:

 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);