SYSK 99: Is [MTAThread] the Only Solution?
By default, Windows apps (WinForms) are marked with STAThread attribute (see Program.cs). So, if you call System.Threading.WaitHandle.WaitAll passing more than one handle in the array you’ll get an exception “WaitAll for multiple handles on an STA thread is not supported”. I’ve seen some posts suggesting you change your application’s apartment mode to MTA. While that solution will work, it may cause problems when using single threaded ActiveX controls, as well as any COM interactions with a single threaded apartment will now cause cross-apartment marshalling, etc.
An alternative is to create a thread that’ll call other methods and wait for their return, and the main thread should wait for that thread to finish execution (WaitOne).
Here is a code snippet that explains what I mean:
This code will throw an exception:
public class WorkerClass
{
public System.Threading.ManualResetEvent Done = new System.Threading.ManualResetEvent(false);
public void DoSomething(object data)
{
Done.Set();
}
}
. . .
WorkerClass c1 = new WorkerClass();
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(c1.DoSomething));
WorkerClass c2 = new WorkerClass();
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(c2.DoSomething));
System.Threading.WaitHandle.WaitAll(new System.Threading.WaitHandle[] { c1.Done, c2.Done });
But this won’t:
. . .
IAsyncResult ar1 = new System.Threading.WaitCallback(ExecuteAsync).BeginInvoke(null, null, this);
ar1.AsyncWaitHandle.WaitOne();
private void ExecuteAsync(object data)
{
WorkerClass c1 = new WorkerClass();
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(c1.DoSomething));
WorkerClass c2 = new WorkerClass();
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(c2.DoSomething));
System.Threading.WaitHandle.WaitAll(new System.Threading.WaitHandle[] { c1.Done, c2.Done });
}
Now you know…
Comments
Anonymous
April 06, 2006
I assume by "Windows apps" you mean WinForms apps?
MTAThread is not supported in WinForms applications. It's more than simply being able to use ActiveX or COM objects within the application. The whole WinForms message pump relies on being in STA, especially when dealing with File dialogs or clipboard operations. Switching to MTA will eventually cause a WinForms application to fail. FxCop will catch the MTAThread attribute.
see http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspxAnonymous
June 03, 2009
REALLY USEFUL POST; I just had met exactly this problem. Thanks a lot.Anonymous
August 28, 2010
The comment has been removed