C# Try/Catch 和线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/778437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Try/Catch and threading
提问by Otávio Décio
I have an idea why but I'd like to ask if someone has a good grasp on why the exception raised inside a thread is never caught by the code that started it. Here's some very simple code to demonstrate what I mean:
我知道为什么,但我想问一下,是否有人很好地理解了为什么在线程内引发的异常从未被启动它的代码捕获。这是一些非常简单的代码来演示我的意思:
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);
}
}
}
}
I naively thought that by having the try/catch I would be safe, but I found out the hard way that it is not the case (it is crashing one of my services).
我天真地认为通过 try/catch 我会是安全的,但我发现事实并非如此(它使我的一项服务崩溃)。
采纳答案by Jon Skeet
Well in general, you've no idea where the originating thread will be by the time the exception is thrown in the new thread - why would it be waiting around for the thread to throw an exception?
总的来说,您不知道在新线程中抛出异常时原始线程将在哪里 - 为什么它会等待线程抛出异常?
Think of the stacks involved - when an exception is thrown, it goes up the stack until it reaches an appropriate catch block. The new thread has a completely separate stack to the creating thread, so it'll never reach the catch block in the creating thread's stack.
想想所涉及的堆栈——当一个异常被抛出时,它会上升到堆栈直到它到达一个合适的 catch 块。新线程与创建线程有一个完全独立的堆栈,因此它永远不会到达创建线程堆栈中的 catch 块。
EDIT: Of course, you could design your system so that the creating thread didwait for other things to happen - a bit like the message loop in a Windows Forms application. The new thread could then catch the exception and send a message to the creating thread, which could then deal with the exception. That isn't the normal setup though - you have to do it all explicitly.
编辑:当然,您可以设计您的系统,以便创建线程确实等待其他事情发生 - 有点像 Windows 窗体应用程序中的消息循环。然后新线程可以捕获异常并向创建线程发送消息,然后创建线程可以处理异常。但这不是正常的设置——你必须明确地做这一切。
回答by John Saunders
It's a bad idea to make assumptions, especially where multiple threads are involved (you know that old saying).
做出假设是一个坏主意,尤其是在涉及多个线程的情况下(您知道那句老话)。
Why wouldthe code that started the thread see the exception? The code that started the thread may not even exist when the exception is thrown.
为什么启动线程的代码会看到异常?抛出异常时,启动线程的代码甚至可能不存在。
回答by Kibbee
The running thread will not be caught in your try/catch statement because it is running in another thread. Try/Catch only works for the current thread. What you need to do is have try/catch in the function being run by the thread, and have some way of managing what happens when that crash occurs.
正在运行的线程不会在您的 try/catch 语句中被捕获,因为它正在另一个线程中运行。Try/Catch 仅适用于当前线程。您需要做的是在线程运行的函数中使用 try/catch,并有某种方法来管理发生崩溃时发生的情况。
回答by 48klocs
You might want to use an EventGeneratingThread wrapper- this will let you catch and deal with exceptions thrown in threads from the process that spawned them.
您可能想要使用EventGeneratingThread 包装器- 这将让您捕获并处理从产生它们的进程的线程中抛出的异常。
回答by Iggy
Try adding this before your DoWork Sub
尝试在 DoWork Sub 之前添加它
<System.Diagnostics.DebuggerNonUserCodeAttribute()> _
I'm using the background worker, and all the Try Catch in my loop work as you'd expect them to with this.
我正在使用后台工作人员,并且我循环中的所有 Try Catch 都按照您期望的方式工作。