使用Task.Factory时捕获错误

我正在使用以下内容

Task.Factory.StartNew(() => DoPrintConfigPage(serial)); 

然后我调用的函数看起来像这样

 private void DoPrintConfigPage(string serial) { //do printing work } 

我的问题是在线程内部抛出exception并且没有被处理。

我试过用try catch包装它

 try { Task.Factory.StartNew(() => DoPrintConfigPage(serial)); } catch (Exception ex) { } 

但它仍然没有捕获错误,从而导致应用程序崩溃。

如何在主线程中捕获exception以便我可以处理它们?

更新

我已经进行了下面推荐的更改,但仍然说exception未处理

 var task = Task.Factory.StartNew(() => DoPrintConfigPage(serial)) .ContinueWith(tsk => { MessageBox.Show("something broke"); },TaskContinuationOptions.OnlyOnFaulted); 

然后在我的DoConfigPage我添加了另一个try catch。

在这个捕获现在崩溃,并说抛出的exception未处理,我错过了什么?

 private void DoPrintConfigPage(string serial) { try { //call the print function } catch (Exception ex) { throw ex; //it is crashing here and saying it is unhandled } } 

我也尝试了Eric J.所提出的相同结果

 var task = Task.Factory.StartNew(() => DoPrintConfigPage(serial)); try { task.Wait(); } catch (AggregateException ex) { MessageBox.Show("something broke"); } 

或者,您可以链接创建任务并添加ContinueWith:

 var job = Task.Factory .StartNew(...) .ContinueWith(tsk => { // check tsk for exception and handle }); 

编辑:此代码片段在运行时会弹出消息框给我:

 void Main() { var serial = "some serial"; var task = Task.Factory .StartNew(() => DoPrintConfigPage(serial)) .ContinueWith(tsk => { MessageBox.Show("something broke"); var flattened = tsk.Exception.Flatten(); // NOTE: Don't actually handle exceptions this way, m'kay? flattened.Handle(ex => { MessageBox.Show("Error:" + ex.Message); return true;}); },TaskContinuationOptions.OnlyOnFaulted); } public void DoPrintConfigPage(string serial) { throw new Exception("BOOM!"); } 

启动新任务后立即退出try块,因为该方法只会继续运行。

相反,您可以将Exception捕获为AggregateException ,等待任务(或多个任务)完成:

 var task1 = Task.Factory.StartNew(() => { throw new MyCustomException("I'm bad, but not too bad!"); }); try { task1.Wait(); } catch (AggregateException ae) { // Assume we know what's going on with this particular exception. // Rethrow anything else. AggregateException.Handle provides // another way to express this. See later example. foreach (var e in ae.InnerExceptions) { if (e is MyCustomException) { Console.WriteLine(e.Message); } else { throw; } } } 

http://msdn.microsoft.com/en-us/library/dd997415.aspx

如果您没有等待任务,我认为最简单的解决方案是在Task.Exception中找到:

获取导致Task过早结束的AggregateException。 如果任务成功完成或尚未抛出任何exception,则返回null。

我正在使用这样的东西:

 Task.Factory.StartNew(() => DoStuffHere()) .ContinueWith(task => { if (task.Exception != null) Log("log all the exceptions!"); }); 

您还应该了解System.Threading.Tasks.TaskScheduler.UnobservedTaskException 。

如果您从事创建“即发即弃” Task实例的业务,则需要在程序开始时订阅该事件。

也许你正试图抓住一个腐败的国家例外 。 由于.NET 4应用程序默认无法捕获此类exception。 您可以尝试将legacyCorruptedStateExceptionsPolicy=true条目添加到配置文件中,如上面链接的MSDN文章中所述。