尝试/捕捉和线程

我知道为什么,但我想问一下是否有人很清楚为什么在一个线程中引发的exception永远不会被启动它的代码捕获。 这是一些非常简单的代码来演示我的意思:

using System; using System.Collections.Generic; using System.Threading; namespace TestCrash { class Program { private static void Crash(object control) { AutoResetEvent are = (AutoResetEvent)(((object[])control)[0]); are.Set(); throw new Exception("Burn baby burn"); } static void Main(string[] args) { try { List waitHandles = new List(); for (int i = 0; i < 100; i++) { AutoResetEvent are = new AutoResetEvent(false); waitHandles.Add(are); object[] procControl = new object[] { are }; ThreadPool.QueueUserWorkItem(Crash, procControl); WaitHandle.WaitAll(waitHandles.ToArray()); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } } 

我天真地认为通过try / catch我会很安全,但我发现事情并非如此(它崩溃了我的一项服务)。

总的来说,在新线程中抛出exception时,你不知道原始线程在哪里 – 为什么它会等待线程抛出exception?

想想所涉及的堆栈 – 当抛出exception时,它会上升到堆栈,直到到达适当的catch块。 新线程与创建线程具有完全独立的堆栈,因此它永远不会到达创建线程堆栈中的catch块。

编辑:当然,您可以设计您的系统,以便创建线程确实等待其他事情发生 – 有点像Windows窗体应用程序中的消息循环。 然后新线程可以捕获exception并向创建线程发送消息,然后可以处理exception。 这不是正常的设置 – 您必须明确地完成所有操作。

做出假设是一个坏主意,特别是在涉及多个线程的情况下(你知道那句老话)。

为什么启动该线程的代码看到exception? 抛出exception时,启动线程的代码甚至可能不存在。

正在运行的线程不会在try / catch语句中捕获,因为它在另一个线程中运行。 Try / Catch仅适用于当前线程。 你需要做的是在线程运行的函数中使用try / catch,并有一些方法来管理崩溃发生时会发生什么。

您可能希望使用EventGeneratingThread包装器 – 这将允许您捕获并处理从生成它们的进程中的线程中抛出的exception。

尝试在DoWork Sub之前添加此项

  _ 

我正在使用后台工作程序,并且我的循环中的所有Try Catch都按照您期望的方式工作。