不支持STA线程上的多个句柄的WaitAll

Ami*_*aei 45 c# multithreading threadpool

  1. 为什么我收到此错误消息?"不支持在STA线程上使用多个句柄的WaitAll."
  2. 我应该使用[MTAThreadAttribute] attribut吗?更新:无法使用WPF应用程序!

注意:它的错误是在WaitHandle.WaitAll(doneEvents)行; 我正在使用标准的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!");
}
Run Code Online (Sandbox Code Playgroud)

更新:以下解决方案不适用于WPF应用程序!无法将主应用程序属性更改为MTAThreadAttribute.这将导致以下错误:

错误: "不支持在STA线程上使用多个句柄的WaitAll."

Cal*_*582 52

实际上我使用以下代替WaitHandle.WaitAll(doneEvents);

foreach (var e in doneEvents)
    e.WaitOne();
Run Code Online (Sandbox Code Playgroud)

  • 我没见过,但我建议使用Task来获取全新的代码 (3认同)
  • 使用这种替代方案有什么缺点吗? (2认同)

Oli*_*ver 20

如何使用任务为您执行线程处理.

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);
Run Code Online (Sandbox Code Playgroud)

  • 它是.NET Framework 4.所以我必须升级项目.这似乎是一种更好的方法! (4认同)
  • `Task.Run(()=> DoSomeWork())`是一个更好的选择 (3认同)

lig*_*t78 10

使用一个ManualResetEvent并等待它.还要维护一个TaskCount变量,该变量设置为您启动的工作线程数,Interlocked.Decrement在工作线程代码中用作工作人员的最后一个操作,并在计数器达到零时发出事件信号,例如

// other worker actions...
if (Interlocked.Decrement(ref taskCount) == 0)
   doneEvent.Set();
Run Code Online (Sandbox Code Playgroud)


Bri*_*eon 7

我会重构你的代码来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!"); 
} 
Run Code Online (Sandbox Code Playgroud)