multithreading应用程序中的exception。

我从一个非常挑剔的人那里听说,在一个线程中抛出(而不是被捕获)的exception正在传播到父线程。 真的吗? 我尝试过这样的东西但是在创建线程中无法捕获exception。

static void Main(string[] args) { ParameterizedThreadStart pts = new ParameterizedThreadStart(ThreadMethod); try { Thread t = new Thread(pts); t.Start(new object()); Console.ReadLine(); } catch (Exception ex) //the exception is not caught { Debugger.Break(); } } static void ThreadMethod(object @object) { Thread.Sleep(2000); throw new IndexOutOfRangeException(); Thread.CurrentThread.Abort(); } 

线程的exception不会传播到主线程的上下文。 这确实有意义 – 在抛出exception时,主线程通常与包含exception处理程序的范围完全不同。

您可以通过挂钩到AppDomain.UnhandledException来捕获这些exception(通常是记录它们)。 有关详细信息,请参阅该页面,包括Windows窗体应用程序的差异等。

不,它不会。 为了捕获线程exception,您需要使用Application.ThreadException。

C#中Threading的一个不错的资源,它有一个用于exception处理的部分: C#中的线程化

exception在调用堆栈中向上传播。

如果从某个方法启动一个新线程,它将向上传播直到它到达该方法。

如果该方法没有捕获它,您将收到一个运行时错误,表明存在未捕获的exception。

这篇关于C#中的线程以及如何处理exception的文章很棒

简而言之,不是没有。 你有几个明显的选择:#

  1. 在新线程启动的方法中记录(在创建的线程的堆栈顶部)。
  2. 使用像异步委托这样的结构,当你调用结束调用时,它将返回一个exception,你可以以正常的方式捕获它。

exception只能在来自的线程上捕获。 因此,在另一个线程上抛出exception不会导致另一个线程捕获它。

没有“父”线程的概念。

这是一种捕捉它并以安全的方式处理它的方法:

 BackgroundWorker bg = new BackgroundWorker(); object o; bg.DoWork += (c1,c2) => { Thread.Sleep(2000); throw new IndexOutOfRangeException(); }; bg.RunWorkerCompleted += (c3,c4) => { if (((RunWorkerCompletedEventArgs)e).Error != null) { MessageBox.Show(((RunWorkerCompletedEventArgs)e).Error.Message); } }; 

当主线程等待另一个线程完成时,有一个非常简单的特殊情况解决方案(参见https://msdn.microsoft.com/en-us/library/58195swd(v=vs.110).aspx) #Examples )。 它只需要一个类exception变量。

由exception处理程序完成的修改后的代码示例可能如下所示。

 using System; using System.Threading; class WaitOne { static AutoResetEvent autoEvent = new AutoResetEvent(false); static Exception SavedException = null; static void Main() { Console.WriteLine("Main starting."); ThreadPool.QueueUserWorkItem( new WaitCallback(WorkMethod), autoEvent); // Wait for work method to signal. autoEvent.WaitOne(); if (SavedException != null) { // handle this exception as you want } Console.WriteLine("Work method signaled.\nMain ending."); } static void WorkMethod(object stateInfo) { Console.WriteLine("Work starting."); // Simulate time spent working. try { Thread.Sleep(new Random().Next(100, 2000)); throw new Exception("Test exception"); } catch (Exception ex) { SavedException = ex; } // Signal that work is finished. Console.WriteLine("Work ending."); ((AutoResetEvent)stateInfo).Set(); } }