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…