3

I have a function that must be running as STA, and I want to propagate its exceptions to calling thread. Here it is:

public void ExceptionBePropagatedThroughHere()
{
  Thread thread = new Thread(TheSTAThread);
  thread.SetApartmentState(ApartmentState.STA);
  thread.Start();
  thread.Join();
}

public void MainFunction()
{
  try
  {
    ExceptionBePropagatedThroughHere();
  }
  catch(Exception e)
  {
     //will not hit here
  }
}

Putting STA attribute on "MainFunction" is not an option here. I noticed if I was using Task, try catch on task join will propagate exception to calling thread, however I cannot specify run a task as STA.

The question is how to propagate exception running as STA to "MainFunction" in the example ablove?

Thanks in advance.

Yuan
  • 2,690
  • 4
  • 26
  • 38
  • 1
    Just store the exception object in a class field. You can't just arbitrarily create an STA thread to keep COM happy, the object that you make calls on must be created on that same thread. Pumping a message loop on the thread is something else that many single-threaded COM servers count on. – Hans Passant May 02 '11 at 23:32

3 Answers3

4

I followed Hans' suggestion and the solution looks like below, no events need to be fired.

private Exception _exception;
public void ExceptionBePropagatedThroughHere()
{
  Thread thread = new Thread(TheSTAThread);Thread thread = new Thread(TheSTAThread);
  thread.SetApartmentState(ApartmentState.STA);
  thread.Start();
  thread.Join();
  if(_exception != null)
    throw new Exception("STA thread failed", _exception);
}

private void TheSTAThread()
{
  try
  {
    //do the stuff
  }
  catch (Exception ex)
  {
    _exception = ex;
  }
}
public void MainFunction()
{
  try
  {
    ExceptionBePropagatedThroughHere();
  }
  catch(Exception e)
  {
     //will not hit here
  }
}
Yuan
  • 2,690
  • 4
  • 26
  • 38
  • Remember to clear the exception as you start the thread otherwise the second time you run this you will get any exception that was caught the first time being re-thrown. Also be aware that this will obviously only work if there is only ever 1 instance of `TheSTAThread` running. – Justin May 03 '11 at 00:38
0

You need to keep a message pump up and running while you are waiting. A Thread.Join is not the option you can use since it will block your thread until the other thread terminates. A very simple message pump is that you create two events called StaThreadExited and StaThreadExceptionEvent. The you can use a WaitHandle.WaitAny on an array of events. If it was an exception event you can fetch it from e.g. a shared variable and rethrow it in your own thread. I have even posted the code here some time ago.

Yours, Alois Kraus

Community
  • 1
  • 1
Alois Kraus
  • 13,229
  • 1
  • 38
  • 64
  • Thread.Join() pumps a message loop when it is called on an STA thread. Clearly it isn't, he wouldn't have to jump through this hoop if it were. – Hans Passant May 02 '11 at 23:30
  • Stack trace is gone in that way, it is been changed to the point where is the new throw is. – Yuan May 03 '11 at 00:07
  • Figured out could reconstruct new exception by putting old one into inner exception, Thanks. – Yuan May 03 '11 at 00:18
0

doesn't matter if the thread is STA or MTA. An uncaught exception in it will crash your application. You can't throw it to the thread that created your misbehaving thread unless you devise a method to do so manually: like catching, storing it somewhere, and notifying the main thread that there was an error

Tudor Carean
  • 972
  • 2
  • 12
  • 22