如何捕获在任务的 ContinueWith 部分抛出的异常?
How to catch an Exception that has been thrown in the ContinueWith part of a task?
在 button_click
事件中,我启动了 Task
以异步执行一些耗时的计算。我使用 Task.ContinueWith
并将继续的 TaskSheduler 设置为 UI 同步上下文,以在 Textbox
.
中显示异步计算的结果
现在假设最后一部分抛出这样的异常:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(DoSomeCalculations).ContinueWith
(t => { throw new Exception("Some Exception"); }, TaskScheduler.FromCurrentSynchronizationContext());
}
如果我启用调试选项 "Enable Just My Code" 然后程序停止并且我收到警告:"Exception was unhandled by user code"
但是如果我不设置这个选项,异常就会消失在任何地方(没有程序崩溃,什么都没有)。
所以how/where我可以处理这个异常吗?
编辑: 请注意,如标签所示,我使用的是 .NET-4.0
如果你想处理异常,那么要么在延续本身中有一个 try/catch 块,以便它处理自己的异常,要么向延续添加一个额外的延续来处理异常。
请注意,如果您使用 await
而不是 ContinueWith
添加延续,通常会更简单,尤其是在处理异常时,因为它会代表您添加延续。
如果您使用的是 .NET Framework 4.5,则有一种处理 Task 对象的新方法。
private async void button1_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
DoSomethingAsync()
});
//this line will run in UI thread
throw new Exception("Some Exception");
}
请注意,当您使用 async 关键字时,Task 对象内发生的任何异常都会被编译器创建的状态机吞没。但是这个异常是在 Task 对象中设置的,所以基本上你仍然可以使用 Task 对象引用这个异常。
供您参考:
http://blog.stephencleary.com/2012/02/async-and-await.html
根据最佳实践,如果我们无法避免使用 async void 方法(尤其是对于事件处理程序),则应在该方法中实现 try catch。但是您需要确保您调用的所有异步方法都具有异步任务方法签名,以便捕获抛出的异常。
在 button_click
事件中,我启动了 Task
以异步执行一些耗时的计算。我使用 Task.ContinueWith
并将继续的 TaskSheduler 设置为 UI 同步上下文,以在 Textbox
.
现在假设最后一部分抛出这样的异常:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(DoSomeCalculations).ContinueWith
(t => { throw new Exception("Some Exception"); }, TaskScheduler.FromCurrentSynchronizationContext());
}
如果我启用调试选项 "Enable Just My Code" 然后程序停止并且我收到警告:"Exception was unhandled by user code"
但是如果我不设置这个选项,异常就会消失在任何地方(没有程序崩溃,什么都没有)。
所以how/where我可以处理这个异常吗?
编辑: 请注意,如标签所示,我使用的是 .NET-4.0
如果你想处理异常,那么要么在延续本身中有一个 try/catch 块,以便它处理自己的异常,要么向延续添加一个额外的延续来处理异常。
请注意,如果您使用 await
而不是 ContinueWith
添加延续,通常会更简单,尤其是在处理异常时,因为它会代表您添加延续。
如果您使用的是 .NET Framework 4.5,则有一种处理 Task 对象的新方法。
private async void button1_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
DoSomethingAsync()
});
//this line will run in UI thread
throw new Exception("Some Exception");
}
请注意,当您使用 async 关键字时,Task 对象内发生的任何异常都会被编译器创建的状态机吞没。但是这个异常是在 Task 对象中设置的,所以基本上你仍然可以使用 Task 对象引用这个异常。
供您参考: http://blog.stephencleary.com/2012/02/async-and-await.html
根据最佳实践,如果我们无法避免使用 async void 方法(尤其是对于事件处理程序),则应在该方法中实现 try catch。但是您需要确保您调用的所有异步方法都具有异步任务方法签名,以便捕获抛出的异常。