我知道为什么但是我想问一下是否有人很清楚为什么在一个线程中引发的异常永远不会被启动它的代码捕获。这里有一些非常简单的代码来证明我的意思:
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<WaitHandle> waitHandles = new List<WaitHandle>();
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);
}
}
}
}
我天真地认为通过尝试/捕获我会安全,但我发现事实并非如此(它正在崩溃我的一项服务)。
答案 0 :(得分:28)
一般情况下,在新线程中抛出异常时,你不知道原始线程的位置 - 为什么它会等待线程抛出异常?
考虑所涉及的堆栈 - 当抛出异常时,它会上升到堆栈,直到到达适当的catch块。新线程与创建线程具有完全独立的堆栈,因此它永远不会到达创建线程堆栈中的catch块。
编辑:当然,您可以设计系统,以便创建线程 等待其他事情发生 - 有点像Windows窗体应用程序中的消息循环。然后,新线程可以捕获异常并向创建线程发送消息,然后可以处理异常。这不是正常的设置 - 你必须明确地完成这一切。
答案 1 :(得分:2)
做出假设是一个坏主意,特别是涉及多个线程的时候(你知道那句老话)。
为什么将启动线程的代码看到异常?抛出异常时,启动线程的代码可能不存在。
答案 2 :(得分:2)
正在运行的线程不会在try / catch语句中捕获,因为它在另一个线程中运行。 Try / Catch仅适用于当前线程。你需要做的是在线程运行的函数中使用try / catch,并有一些方法来管理崩溃发生时会发生什么。
答案 3 :(得分:2)
您可能希望使用EventGeneratingThread wrapper - 这将允许您捕获并处理从生成它们的进程中的线程中抛出的异常。
答案 4 :(得分:2)
尝试在DoWork Sub
之前添加此内容<System.Diagnostics.DebuggerNonUserCodeAttribute()> _
我正在使用后台工作程序,并且我的循环中的所有Try Catch都按照您的预期使用它。