WaitAll para múltiples manejadores en un hilo STA no es compatible


  1. ¿Por qué recibo este mensaje de error? "WaitAll para múltiples controladores en un hilo STA no es compatible."
  2. ¿Debo usar [MTAThreadAttribute] attribut? Actualización: No funciona con aplicaciones WPF!

Nota: El error está en la línea WaitHandle.WaitAll (doneEvents); Estoy usando un proyecto estándar 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 MTAThreadAttribute. El resultado será el siguiente error:

Error: "WaitAll para múltiples controladores en un hilo STA no es compatible."

Author: casperOne, 2010-11-16

5 answers

¿Qué hay de usar las tareas para hacer su threading 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);
 18
Author: Oliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-16 12:24:21

En realidad uso lo siguiente para reemplazar WaitHandle.En este caso, el valor de los datos se calculará de la siguiente manera:]}

foreach (var e in doneEvents)
    e.WaitOne();
 47
Author: Calimero100582,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-24 11:40:21

Usa uno ManualResetEvent y espera en él. También mantenga una variable TaskCount que se establezca en el número de subprocesos de trabajo que inicie, use Interlocked.Decrement en el código del subproceso de trabajo como la última acción del worker y señale el evento si el contador llega a cero,por ejemplo,

// other worker actions...
if (Interlocked.Decrement(ref taskCount) == 0)
   doneEvent.Set();
 9
Author: liggett78,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-16 12:00:33

Refactorizaría su código para usar la clase CountdownEvent en su 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!"); 
} 
 6
Author: Brian Gideon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-16 14:03:41

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);
 0
Author: CSharper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-16 10:49:13