捕获在不同线程中抛出的exception

我的一个方法(方法Method1 )产生一个新的线程。 该线程执行一个方法( Method2 ),并在执行期间引发exception。 我需要获取有关调用方法( Method1 )的exception信息

有什么方法可以捕获在Method1中引发的Method1中的此exception?

.NET 4及以上版本中,可以使用Task<T>类而不是创build新线程。 然后,您可以使用任务对象上的.Exceptions属性来获取exception。 有两种方法可以做到这一点:

  1. 在一个单独的方法:/ /你在一些任务的线程处理exception

     class Program { static void Main(string[] args) { Task<int> task = new Task<int>(Test); task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted); task.Start(); Console.ReadLine(); } static int Test() { throw new Exception(); } static void ExceptionHandler(Task<int> task) { var exception = task.Exception; Console.WriteLine(exception); } } 
  2. 在相同的方法:/ /你在调用者的线程处理exception

     class Program { static void Main(string[] args) { Task<int> task = new Task<int>(Test); task.Start(); try { task.Wait(); } catch (AggregateException ex) { Console.WriteLine(ex); } Console.ReadLine(); } static int Test() { throw new Exception(); } } 

请注意,您得到的exception是AggregateException 。 所有真正的exception都可以通过ex.InnerExceptions属性获得。

.NET 3.5中,您可以使用以下代码:

  1. //你在线程中处理exception

     class Program { static void Main(string[] args) { Exception exception = null; Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), Handler)); thread.Start(); Console.ReadLine(); } private static void Handler(Exception exception) { Console.WriteLine(exception); } private static void SafeExecute(Action test, Action<Exception> handler) { try { test.Invoke(); } catch (Exception ex) { Handler(ex); } } static void Test(int a, int b) { throw new Exception(); } } 
  2. 或者//你在调用者的线程中处理exception

     class Program { static void Main(string[] args) { Exception exception = null; Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), out exception)); thread.Start(); thread.Join(); Console.WriteLine(exception); Console.ReadLine(); } private static void SafeExecute(Action test, out Exception exception) { exception = null; try { test.Invoke(); } catch (Exception ex) { exception = ex; } } static void Test(int a, int b) { throw new Exception(); } } 

Method1中无法捕获exception。 但是,您可以在Method2中捕获exception,并将其logging到原始执行线程可以读取和使用的variables中。

在不同线程之间共享数据的最简单的方法是shared data如下(有些是伪代码):

 class MyThread { public string SharedData; public void Worker() { ...lengthy action, infinite loop, etc... SharedData = "whatever"; ...lengthy action... return; } } class Program { static void Main() { MyThread m = new MyThread(); Thread WorkerThread = new Thread(m.Worker); WorkerThread.Start(); loop//or eg a Timer thread { f(m.SharedData); } return; } } 

你可以在这个关于multithreading的很好的介绍中看到这个方法,但是我更愿意在O'Reilly book C# 3.0 in a nutshell地阅读一下,这O'Reilly book C# 3.0 in a nutshell也可以在Google Books上免费获得,就像本书的较新版本一样,因为它也包含了线程池,前台线程和后台线程等等,以及简单的示例代码。 (免责声明:我拥有本书的一个破旧的副本)

如果你正在制作一个WinForms应用程序,使用共享数据特别方便,因为WinForm控件不是线程安全的。 使用callback将数据从工作者线程传递回WinForm控件,主UI线程需要使用Invoke()难看代码才能使该控件成为线程安全的。 使用共享数据而不是单线程的System.Windows.Forms.Timer ,使用0.2秒的短时间Interval ,可以轻松地将工作线程的信息发送到控件,而无需Invoke

你可以使用这样的东西:

 Thread thread = new Thread(delegate() { try { MyIPoller.Start(); } catch(ThreadAbortException) { } catch(Exception ex) { //Handle } finally { } }); 

这将确保exception不会使其到线程的顶部。