2

我写了这个代码片段:

        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 方法。

我在调试和不调试的情况下都运行了它,并且行为是相同的。

任何想法我做错了什么?

4

4 回答 4

7

自 .NET 2.0 以来,未处理的异常会终止程序。认为主线程被“中断”并不是正确的心态,整个程序被中止,所有线程都死了。它是 Thread.Abort() 的“粗鲁”版本,无法停止。

AppDomain.UnhandledException 事件发生了最后的喘息。它触发让您有机会记录 e.UnhandledException.ToString() 的值,以便您可以诊断崩溃。顺便说一句,经常被忽视,但是当你的程序在野外出现并且用户和他们的机器以你没有想到的非常令人惊讶的方式对待你的程序时,处理崩溃是必不可少的。

使用 .config 文件中覆盖默认 CLR 策略的属性实际上可以不使程序崩溃。但是这种方式很疯狂,线程在没有完成工作的情况下终止只会导致程序以完全无法诊断的方式出现异常。在 .NET 1.x 中尝试过,但作为一个坏主意被拒绝。

于 2013-06-21T16:45:48.893 回答
1

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

the child thread terminates silently

可能是,只是您所描述的可能来自 .NET 1.x 的远古时代。从 .NET 2.0 及更高版本开始,这不再适用。

总而言之,有一些方法可以使线程不使程序崩溃。(这只是为了演示,不是为了练习。永远不要这样做)。

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

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

看看 C# 4.0 Task Parallel Library 和 C# 5.0 async/await 了解一些 .NET/C# 的精彩之处。

于 2013-06-21T16:25:50.817 回答
0

你的理解几乎是正确的。

线程中任何未处理的异常(除了ThreadAbortException)都会沿着调用堆栈有效地粉碎它。然后线程被默默地杀死。但灾难并不止于此。然后异常继续消耗整个运行过程。但就在进程被杀死之前,AppDomain.UnhandledException会引发事件。它使您有机会记录异常(或发出很抱歉的消息)。的isTerminating属性UnhanledExceptionEventArgs总是true

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

现在解释一下您所看到的,第二个线程(不是子线程)中的异常并没有中断或影响第一个线程。第二个线程被杀死。然后整个过程被杀死。一旦进程被杀死,第一个线程就无处可藏。它注定要死。现在,如果代码在 Visual Studio 中运行(附加了调试器),调试器一旦意识到没有catch块可以捕获它,就可以捕获异常。那就是当您看到它在主线程中中断时。调试器不只是中断主线程,它正在暂停所有线程,包括发生异常的线程。它使您有机会修改代码并恢复它。

如果没有调试器,异常会吃掉自己的线程,然后消耗整个进程。

于 2013-06-21T16:20:27.933 回答
0

未处理的异常会产生不同的结果,如下所示。

  1. 如果使用 Thread 类显式运行线程,则任何未处理的异常都会导致应用程序关闭。
  2. 如果使用线程池运行线程(使用 TPL、ThreadQueueWorker、任何其他方式)如果使用任务非泛型对象,则不会导致应用程序崩溃 b. 如果使用任务,则会导致应用程序崩溃。
于 2018-03-25T10:38:18.610 回答