捕获在不同线程中抛出的exception
我的一个方法(方法Method1
)产生一个新的线程。 该线程执行一个方法( Method2
),并在执行期间引发exception。 我需要获取有关调用方法( Method1
)的exception信息
有什么方法可以捕获在Method1
中引发的Method1
中的此exception?
在.NET 4及以上版本中,可以使用Task<T>
类而不是创build新线程。 然后,您可以使用任务对象上的.Exceptions
属性来获取exception。 有两种方法可以做到这一点:
-
在一个单独的方法:/ /你在一些任务的线程处理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); } }
-
在相同的方法:/ /你在调用者的线程处理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中,您可以使用以下代码:
-
//你在子线程中处理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(); } }
-
或者//你在调用者的线程中处理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不会使其到线程的顶部。