Task.ContiueWith 内部发生处理异常
Handling exception occured inside Task.ContiueWith
我正在研究 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());
}
but when exception occurred in second action(success) they are ignored
and nothing happens
因为您没有将代码包装在 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);
}
}
我正在研究 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());
}
but when exception occurred in second action(success) they are ignored and nothing happens
因为您没有将代码包装在 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);
}
}