在阅读有关任务和exepcion管理的信息后,我使用此代码来管理任务中抛出的异常:
Task<Object> myTask = Task.Factory.StartNew<Object>(doTask, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
myTask .ContinueWith(task => afterTask(task), TaskScheduler.FromCurrentSynchronizationContext());
doTask和AfterTask在哪里:
private <Object> doTask() {
throw new Exception("BOOM");
}
private afterTask(Task<Object> aTask) {
if (aTask.IsFaulted)
{
MessageBox.Show(aTask.Exception.InnerException.Message);
}
else //whatever
}
当抛出Exception Boom时,Visual Studio会显示一条警告,通知未捕获异常但如果我继续执行异常则在afterTask函数中处理。
这段代码是否正确或我错过了解任务的一些基本行为?有什么办法可以避免调试器发出没有捕获到execption的警告?有点烦人......
提前致谢
答案 0 :(得分:21)
请改为尝试:
task.ContinueWith(
t =>
t.Exception.Handle(ex =>
{
logger.Error(ex.Message, ex);
return false;
})
, TaskContinuationOptions.OnlyOnFaulted
);
通过使用TaskContinuationOptions.OnlyOnFaulted
,只有在原始任务抛出异常时才运行ContinueWith
块。
另外,您可以选择是否从传递给Handle
的lambda返回true或false,指示是否已处理异常。就我而言,我不想阻止异常传播。您可能希望将其更改为在您的案例中返回true
。
答案 1 :(得分:-3)
try
{
var t1 = Task.Delay(1000);
var t2 = t1.ContinueWith(t =>
{
Console.WriteLine("task 2");
throw new Exception("task 2 error");
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var t3 = t2.ContinueWith(_ =>
{
Console.WriteLine("task 3");
return Task.Delay(1000);
}, TaskContinuationOptions.OnlyOnRanToCompletion).Unwrap();
// The key is to await for ALL tasks rather than just
// the first or last task.
await Task.WhenAll(t1, t2, t3);
}
catch (AggregateException aex)
{
aex.Flatten().Handle(ex =>
{
// handle your exceptions here
Console.WriteLine(ex.Message);
return true;
});
}