正在处理Task.ContinueWith内部发生的异常
本文关键字:异常 内部 ContinueWith 处理 Task | 更新日期: 2023-09-27 17:59:41
我正在研究wpf,我已经编写了以下代码,以显示从web服务获取数据时发生的异常。
有两种操作方法,第一种是调用远程服务,第二种是在得到结果时更新UI对象。
当第一个操作(初始)中发生异常时,我正确地获得了异常框,但当第二个操作(成功)中出现异常时,它们被忽略,什么都没有发生。事件断点未在continue with的最后一行命中。
我想知道发生了什么以及最好的解决方案。这种类型的异常不能全局处理吗?
private void ExecuteSafely(string message, Action intial, Action successAction)
{
var task = Task.Factory.StartNew(intial);
task.ContinueWith(t =>
{
if (t.Exception != null)
{
HandleException(t.Exception);
}
else
{
successAction.Invoke();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
但当第二个操作(成功)中出现异常时,它们将被忽略什么也没发生
因为您没有将代码包装在try-catch
块中,因此该异常不会被处理,而是被您的继续任务所吞噬。
要抓住它,请进行包装:
private void ExecuteSafely(string message, Action initial, Action successAction)
{
var task = Task.Factory.StartNew(initial).ContinueWith(t =>
{
if (t.Exception != null)
{
HandleException(t.Exception);
}
else
{
try
{
successAction();
}
catch (Exception e)
{
// Handle your exception.
}
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
如果您使用的是.NET 4.0,则吞噬的异常最终将在Task
的定稿过程中抛出。
如果您使用的是.NET 4.5,async-await
将不那么冗长:
private async Task ExecuteSafelyAsync(string message,
Action initial,
Action successAction)
{
try
{
var task = await Task.Run(initial);
successAction();
}
catch (Exception e)
{
// You get here if either Task.Run or successAction throws
}
}
当你调用它时:
await ExecuteSafelyAsync("hello", initial, success);
successAction抛出异常时,UI线程无法捕获异常,因为successAction没有在UI线程上调用。
如果你在.net 4.5上工作,我认为你应该使用async/await,比如:
private async void ExecuteSafely(string message, Action intial, Action successAction)
{
try
{
await Task.Factory.StartNew(intial);
successAction.Invoke();
}
catch (Exception e)
{
HandleException(e);
}
}