2011-05-02 85 views
3

我有一个函数,必须作为STA运行,我想传播它的异常到调用线程。这里是:STA线程异常传播

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 
    } 
} 

在“MainFunction”上放置STA属性在这里不是一个选项。 我注意到,如果我使用任务,尝试抓住任务加入将传播异常到调用线程,但是我不能指定运行任务作为STA。

问题是如何将例外运行作为STA传播到示例ablove中的“MainFunction”?

在此先感谢。

+1

只将异常对象存储在类字段中。你不能随意创建一个STA线程来保持COM的快乐,你创建的对象必须在同一个线程上创建。在线程上传递消息循环是许多单线程COM服务器所依赖的东西。 – 2011-05-02 23:32:36

回答

4

我遵循Hans的建议解决方案如下所示,不需要触发任何事件。

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 
    } 
} 
+0

记得在启动线程时清除异常,否则第二次运行时会得到第一次被重新抛出的异常。另外请注意,如果只有1个'TheSTAThread'实例在运行,这显然是有效的。 – Justin 2011-05-03 00:38:44

0

您需要在等待时保持消息泵正常运行。一个Thread.Join不是你可以使用的选项,因为它会阻塞你的线程直到另一个线程终止。 一个非常简单的消息泵是您创建了两个名为StaThreadExited和StaThreadExceptionEvent的事件。您可以在事件数组上使用WaitHandle.WaitAny。如果是例外事件,您可以从例如一个共享变量,并在自己的线程中重新抛出它。我甚至在一段时间前发布了code

你的, 阿洛伊斯·克劳斯

+0

Thread.Join()在STA线程上调用它时传递消息循环。显然不是,如果是这样的话,他不必跳过这个箍。 – 2011-05-02 23:30:33

+0

堆栈跟踪以这种方式消失了,它已被更改为新投掷的位置。 – Yuan 2011-05-03 00:07:15

+0

想通过将旧的内置异常重新构造新的异常,谢谢。 – Yuan 2011-05-03 00:18:41

0

如果线程是STA或MTA没有关系。未捕获的异常会导致应用程序崩溃。除非你设计一种手动方法,否则你不能把它扔到创建你的行为异常的线程的线程上:如捕获,将它存储在某处,并通知主线程有错误