问题
- Why do I get this error message? "WaitAll for multiple handles on a STA thread is not supported."
- Should I use [MTAThreadAttribute] attribut? Update: Dosn't work with WPF applications!
Note: It error is at line WaitHandle.WaitAll(doneEvents); I'm using a standard WPF project.
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: The following solution doesn’t work for WPF applications! It is not possible to change the main application attribute to MTAThreadAttribute. It will result in the following error:
Error: "WaitAll for multiple handles on a STA thread is not supported."
回答1:
What about using the Tasks to do your threading for you.
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);
回答2:
Actually I use the following to replace WaitHandle.WaitAll(doneEvents);
foreach (var e in doneEvents)
e.WaitOne();
回答3:
Use one ManualResetEvent and wait on it. Also maintain a TaskCount variable that is set to the number of worker threads you start, use Interlocked.Decrement in the worker thread code as the very last action of the worker and signal the event if the counter reaches zero,e.g.
// other worker actions...
if (Interlocked.Decrement(ref taskCount) == 0)
doneEvent.Set();
回答4:
I would refactor your code to use the CountdownEvent class instead.
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!");
}
回答5:
use something like this:
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);
来源:https://stackoverflow.com/questions/4192834/waitall-for-multiple-handles-on-a-sta-thread-is-not-supported