2013-06-21 103 views
1

我写了这个代码片段:.NET多线程和异常

 static void Main(string[] args) 
    { 
     Console.WriteLine("Start"); 

     Thread secondThread = new Thread(ThrowAnException); 
     secondThread.Start(); 

     Console.ReadKey(); 
    } 

    static void ThrowAnException() 
    { 
     throw new Exception("Second Thread Exception"); 
    } 
} 

我的理解是,当异常发生时,第二个线程上的异常,如果未处理,子线程下移线程的堆栈和默默终止。我所看到的是这个线程正在中断主线程,并在ThrowAnException方法中抛出了“Exception was Unhandled”异常。

我运行它与调试和没有和行为是相同的。

任何想法我做错了什么?

+1

[.NET线程抛出异常时会发生什么?](http://stackoverflow.com/questions/1668634/what-happens-when-a-net-thread-throws-an-exception) – Euphoric

+0

你“看到线程正在中断主线程”吗? – Timbo

+1

'孩子的线程默默地终止了 - 你在哪里遇到过这个? – YK1

回答

7

自.NET 2.0以来未处理的异常终止程序。认为主线程被“中断”并不是正确的思维定势,整个程序会中止并且线程全部死亡。这是Thread.Abort()的“粗鲁”版本,无法停止。

通过AppDomain.UnhandledException事件有一个最后的喘息。它触发了给你一个记录e.UnhandledException.ToString()值的机会,所以你将有机会诊断崩溃。经常被忽视的btw,但必不可少的处理崩溃当你的程序在野外发生,用户和他们的机器经常在你的程序中处理你的程序令人惊讶的方式,你没有设想。

它实际上可能不会使用覆盖默认CLR策略的.config文件中的属性使程序崩溃。但这就是疯狂,终止而没有完成工作的线程只会导致程序以完全不可知的方式行事不端。在.NET 1.x中尝试并被拒绝为一个糟糕的想法。

0

你的理解几乎是正确的。

线程中的任何未处理的异常(除ThreadAbortException)都会导致调用堆栈崩溃。然后线程被无声地杀死。但灾难并不止于此。该异常继续消耗整个运行过程。但是在进程被杀之前,AppDomain.UnhandledException事件被引发。它给你一个记录异常的机会(或者提出一个很大的遗憾信息)。 UnhanledExceptionEventArgsisTerminating财产总是true

需要注意的是,在dot-net中,线程间没有父子关系。所有线程都是相等的。 下面的唯一的一个线程是AppDomain本身。

现在来解释一下你看到的第二个线程(而不是子线程)的异常没有中断或反正影响第一个线程。第二个线程被杀害。那么整个过程就会被杀死。一旦进程被杀死,第一个线程无处藏身。它注定要死亡。现在如果代码在Visual Studio中运行(调试器已连接),调试器会在意识到没有catch块来捕获该异常时立即捕获该异常。那就是当你看到它闯入的主线程。调试器不只是在主线程中断,而是暂停所有线程,包括发生异常的线程。它给你一个修改代码并恢复的机会。

没有调试器,异常吃掉自己的线程,然后它消耗整个过程。

+0

实际上,饮食和消费少得多。当CLR检测到未处理的异常时,它会关闭。正如你所建议的那样,线程/进程没有任何破坏性。 –

+0

感谢所有的答案 - 如果我可以标记所有3正确的我会。 –

0

你看到的是正确的行为。用户启动的任何线程中的未处理异常都会导致程序崩溃。

the child thread terminates silently

可能,只是也许你所描述的是从.NET 1.x的古天这从.NET 2.0及更高版本中不再是真实的。

所有说,有人可以让线程不会使程序崩溃的方法。 (这只是为了演示,不是为了练习,从来不这样做)。

Action a = ThrowAnException; 
    a.BeginInvoke(null, null); 

这将导致使用APM在ThreadPool线程上调用ThrowAnException。在拨打EndInvoke之前,您永远不会看到异常情况。但是,APM不再是推荐的异步方式。

看看C#4.0任务并行库和C#5.0异步/等待某些.NET/C#awesomeness。