2010-11-16 15 views
38
  1. Perché viene visualizzato questo messaggio di errore? "WaitAll per più handle su un thread STA non è supportato."
  2. Devo usare [MTAThreadAttribute] attribuire? Aggiornamento: Non funziona con le applicazioni WPF!

Nota: Errore nella riga WaitHandle.WaitAll (doneEvents); Sto utilizzando un progetto standard WPF.WaitAll per più handle su un thread STA non supportato

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

Update: La seguente soluzione non funziona per applicazioni WPF! Non è possibile modificare l'attributo dell'applicazione principale su MTAThreadAttribute. Risulterà il seguente errore:

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

+0

Ti rendi conto che si app congelare completamente fino a quando tali indicizzatori sono fatto? – liggett78

+0

Sì! Lo so. Ma così com'è non funziona. –

+1

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

risposta

17

Che ne dici di utilizzare le attività per fare il 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); 
+4

È .NET Framework 4. Quindi devo aggiornare il progetto. Sembra essere un approccio migliore pensato! –

+2

'Task.Run (() => DoSomeWork())' è un'alternativa migliore – gldraphael

8

Utilizzare uno ManualResetEvent e attendere. 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 es.

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

Grazie sembra essere l'unica soluzione poiché WaitAll (..) non funziona. –

+0

Sì, funzionerebbe. Assicurati di considerare il thread principale come se fosse un elemento di lavoro e inizializza 'taskCount = 1' e fai il' Decrement' e 'Set' alla fine del ciclo' for'. –

6

avrei refactoring il codice per utilizzare la classe CountdownEvent invece.

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

realtà Uso quanto segue per sostituire WaitHandle.WaitAll (doneEvents);

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

ci sono degli svantaggi nell'usare questa alternativa? – invertigo

+3

Non ne ho visto nessuno, ma consiglierei di usare Task per il nuovo codice – Calimero100582

0

uso qualcosa di simile:

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 è di tipo System.Threading.AutoResetEvent – CSharper

+0

-1 Pur essendo più pulito, per me questo non è sufficientemente diverso da http://stackoverflow.com/a/4194938/11635 –

Problemi correlati