线程化时的异常 - 线程之间的传播?

时间:2012-07-18 15:50:52

标签: c# .net multithreading exception .net-3.5

如果我遇到以下情况:

  1. Execute()创建一个新线程并在其中执行函数GetSession()。
  2. Execute()再次在它自己的线程中执行GetSession()。
  3. Execute()从(1)加入线程。

  4. 我的问题是:

    当运行线程Execute()时,GetSession()从(1)中生成的线程抛出异常当前正在运行GetSession()本身会发生什么?

    从额外线程重新抛出的异常是否会传播到Execute()并导致它转到其处理程序,即使它来自另一个线程?


    以下是一些展示问题的示例代码:

    我刚刚在这里的窗口中做了这个(这是一个模型),所以对语法错误有所了解。

    public void Execute()
    {
        //Some logon data for two servers.
        string server1 = "x", server2 = "y", logon = "logon", password = "password";
    
        //Varialbes to store sessions in.
        MySession session1, session2;
    
        try
        {
            //Start first session request in new thread.
            Thread thread = new Thread(() =>
                session1 = GetSession(server1, logon, password));
            thread.Start();
    
            //Start second request in current thread, wait for first to complete.
            session2 = GetSession(server2, logon, password));
            thread.Join();
        }
        catch(Exception ex)
        {
            //Will this get hit if thread1 throws an exception?
            MessageBox.Show(ex.ToString());
            return;
        }
    }
    
    private MySession GetSession(string server, string logon, string password)
    {
        try
        {
            return new MySession(server, logon, password);
        }
        catch(Exception Ex)
        {
            throw(Ex);
        }
    }
    

1 个答案:

答案 0 :(得分:5)

  

当运行线程Execute()时,GetSession()从(1)中生成的线程抛出异常当前正在运行GetSession()本身会发生什么?

线程版本将引发未处理的异常,这将触发AppDomain.UnhandledException。除非在那里明确处理,否则它将拆除应用程序。

  

从额外线程重新抛出的异常是否会传播到Execute()并导致它转到其处理程序,即使它来自不同的线程?

没有。它将无法处理。


请注意,这是TPL的优势之一。如果您使用Task而不是Thread,那么可以使这个异常传回主线程:

try
{
    //Start first session request in new thread.
    Task<Session> task = Task.Factory.StartNew(() => GetSession(server1, logon, password));

    //Start second request in current thread, wait for first to complete.
    session2 = GetSession(server2, logon, password));
    session1 = task.Result; // This blocks, and will raise an exception here, on this thread
}
catch(Exception ex)
{
    // Now this will get hit
    MessageBox.Show(ex.ToString());
    return;
}

但请注意,这将是AggregateExceptionrequires special handling