C# 线程中的异常处理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1554181/
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
Exception handling in threads
提问by user184805
Recently i have attended an interview . A code snippet is given to me.I know,the interviewer took it from albhari's threading sample.
最近我参加了一个面试。给了我一个代码片段。我知道,面试官从albhari的线程示例中获取了它。
public static void Main()
{
try
{
new Thread (Go).Start();
}
catch (Exception ex)
{
// We'll never get here!
Console.WriteLine ("Exception!");
}
}
static void Go() { throw null; }
The modification of the above code as
将上述代码修改为
public static void Main()
{
new Thread (Go).Start();
}
static void Go()
{
try
{
...
throw null; // this exception will get caught below
...
}
catch (Exception ex)
{
Typically log the exception, and/or signal another thread
that we've come unstuck
...
}
}
would be the good candidate to handle the exception.
将是处理异常的好人选。
I have been asked, "Except the above trail what are the other alternatives would fit as good solution?. It was hard to find the alternative,so i raise it here to gather your suggestion.
有人问我,“除了上述线索,还有哪些其他替代方案适合作为好的解决方案?。很难找到替代方案,所以我在这里提出它以收集您的建议。
采纳答案by elder_george
Exception thrown in a thread normally couldn't be caught in another thread.
在一个线程中抛出的异常通常无法在另一个线程中捕获。
You'd better to catch it in function Go and pass it to main thread explicitly.
您最好在函数 Go 中捕获它并将其显式传递给主线程。
However, if you just want to log all unhandled messages from all threads, you may use AppDomain.UnhandledExceptionevent or equivalent events at Application class if you are developing WinForms or WPF app.
但是,如果您只想记录来自所有线程的所有未处理的消息,如果您正在开发 WinForms 或 WPF 应用程序,则可以在 Application 类中使用AppDomain.UnhandledException事件或等效事件。
回答by Thomas Levesque
You can use the AppDomain.UnhandledException
event
您可以使用该AppDomain.UnhandledException
事件
回答by Cheeso
what are the other alternatives would fit as good solution?.
还有哪些其他选择适合作为好的解决方案?
Solution to what?What problem are you trying to solve?
解决什么问题?你想解决什么问题?
If you use BackgroundWorker, as opposed to Thread, it has an RunWorkerCompletedevent, and within that you can check the RunWorkerCompletedEventArgsparam for the Error property. This generally is used in WinForms or WPF apps, because there is good support for BackgroundWorker in the Visual Studio designer.
如果您使用BackgroundWorker,而不是 Thread,它有一个RunWorkerCompleted事件,您可以在其中检查RunWorkerCompletedEventArgs参数的 Error 属性。这通常用于 WinForms 或 WPF 应用程序,因为 Visual Studio 设计器中对 BackgroundWorker 有很好的支持。
You could also define a delegate for Go(), and call BeginInvoke() on it. Of course you need the EndInvoke() too.
您还可以为 Go() 定义一个委托,并在其上调用 BeginInvoke()。当然,您也需要 EndInvoke()。
Also, it's generally not a good idea to start up random threads. ThreadPool.QueueUserWorkItem, BackgroundWorker, or asynch delegates all use the ThreadPool, and are recommended.
此外,启动随机线程通常不是一个好主意。ThreadPool.QueueUserWorkItem、BackgroundWorker 或异步委托都使用 ThreadPool,建议使用。
回答by jrupe
There are alternatives listed on Joe Albahari's website: http://www.albahari.com/threading/#_Exception_Handling
Joe Albahari 的网站上列出了替代方案:http: //www.albahari.com/threading/#_Exception_Handling
"There are, however, some cases where you don't need to handle exceptions on a worker thread, because the .NET Framework does it for you. These are covered in upcoming sections, and are:
-Asynchronous delegates
-BackgroundWorker
-The Task Parallel Library (conditions apply)"
“有,但是,有些情况下,你并不需要一个工作线程处理异常,因为.NET Framework会为你这些都属于即将到来的部分,并且是:
-Asynchronous代表
-BackgroundWorker
-The任务并行库(有条件)”
回答by max
I think this is the easiest way is:
我认为这是最简单的方法是:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler((object sender2, DoWorkEventArgs e2) =>
{
throw new Exception("something bad");
e2.Result = 1 + 1;
});
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((object sender2, RunWorkerCompletedEventArgs e2) =>
{
if (e2.Error != null)
{
Console.WriteLine("Error: " + e2.Error.Message);
}
});
bw.RunWorkerAsync();
but there is another way that some might prefer if you want to synchronize the thread (perhaps this is on a thread other than the GUI thread):
但是如果您想同步线程,有些人可能更喜欢另一种方式(也许这是在 GUI 线程以外的线程上):
private class FileCopier
{
public bool failed = false;
public Exception ex = null;
public string localPath;
public string dstPath;
public FileCopier(string localPath, string dstPath)
{
this.localPath = localPath;
this.dstPath = dstPath;
}
public void Copy()
{
try{
throw new Exception("bad path");
}catch(Exception ex2)
{
ex = ex2;
failed = true;
}
}
}
public static void Main()
{
FileCopier fc = new FileCopier("some path", "some path");
Thread t = new Thread(fc.Copy);
t.Start();
t.Join();
if (fc.failed)
Console.WriteLine(fc.ex.Message);
}
Note that the second example would make more sense if you have several threads and you loop through them and join all...but I kept the example simple.
请注意,如果您有多个线程并循环遍历它们并加入所有线程,那么第二个示例会更有意义……但我使示例保持简单。
the 3rd pattern would be using Task Factory which is cleaner:
第 3 种模式将使用更清洁的任务工厂:
private static test(){
List<Task<float>> tasks = new List<Task<float>>();
for (float i = -3.0f; i <= 3.0f; i+=1.0f)
{
float num = i;
Console.WriteLine("sent " + i);
Task<float> task = Task.Factory.StartNew<float>(() => Div(5.0f, num));
tasks.Add(task);
}
foreach(Task<float> t in tasks)
{
try
{
t.Wait();
if (t.IsFaulted)
{
Console.WriteLine("Something went wrong: " + t.Exception.Message);
}
else
{
Console.WriteLine("result: " + t.Result);
}
}catch(Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
private static float Div(float a, float b)
{
Console.WriteLine("got " + b);
if (b == 0) throw new Exception("Divide by zero");
return a / b;
}