C# 如何从已取消的任务中获取内部异常?
我有一个任务,如果出现异常,将取消使用sme取消令牌的任务并引发异常:C# 如何从已取消的任务中获取内部异常?,c#,task-parallel-library,C#,Task Parallel Library,我有一个任务,如果出现异常,将取消使用sme取消令牌的任务并引发异常: var cancellationTokenSource = new CancellationTokenSource(); var task1 = Task.Factory.StartNew( () => { try {
var cancellationTokenSource = new CancellationTokenSource();
var task1 = Task.Factory.StartNew(
() =>
{
try
{
// Do work
}
catch (Exception exception)
{
cancellationTokenSource.Cancel();
// rethrow the error
throw;
}
},
cancellationTokenSource.Token,
TaskCreationOptions.None,
taskScheduler);
我还有另一个task3(返回任务),它是task1和task2的延续,并使用相同的取消标记:
return task3 =
Task.Factory.ContinueWhenAll(
new[] { task1, task2 },
tasks =>
{
// Do work
},
cancellationTokenSource.Token,
TaskContinuationOptions.None,
this.taskScheduler).Unwrap();
一旦task1被取消,具有相同取消令牌的所有任务也将被取消。
我需要获取task1抛出的内部异常,以及如何实现它?使用异步/等待和常规异常处理如何?不过它需要.NET4.5。类似这样的情况(我不知道任务之间必须如何交互,因此您的代码可能最终看起来完全不同): 更新:我更新了代码以使用WhenAll 更新:更新了代码以使用任务创建任务。运行方法而不是使用冷任务 更新:您可以省略async/await(尽管我认为这样更好),并执行一些老式的TPL错误处理。不要对task3(返回任务)使用取消令牌,只对它正在等待的任务使用取消令牌。当它们完成时(正常情况下,或通过异常/取消),您可以这样处理task3中的异常:
// don't use the cancellation token for the third task as you used for the previous ones
var task3 = Task.Factory.ContinueWhenAll(
new[] { task1, task2 },
tasks =>
{
if (tasks[0].Exception != null)
{
tasks[0].Exception.Handle(exc =>
{
Console.WriteLine("First task failed :(");
return false; // signal that exception was handled, so it won't propagate
});
// add additional code here, or inside the Handle method above
}
if (tasks[1].Exception != null)
{
tasks[1].Exception.Handle(exc =>
{
Console.WriteLine("Second task failed :(");
return false; // signal that exception was handled, so it won't propagate
});
// add additional code here, or inside the Handle method above
}
// do the same for the rest of the tasks or iterate throught them with a foreach loop...
});
返回冷任务不符合TPL指南。你应该使用
task返回一个热任务。改为运行。Yuval,你能按照我原来的语法发布代码吗?Yuval:很高兴知道。我更新了代码以使用热任务。安娜R:你的意思是使用没有异步/等待的任务?是的,就像我发布的代码一样。有没有可能像代码中那样从已取消的任务中获取异常?我想我现在就得到了。我相应地更新了代码。请问您为什么要这样使用它,而不是async/await?
// don't use the cancellation token for the third task as you used for the previous ones
var task3 = Task.Factory.ContinueWhenAll(
new[] { task1, task2 },
tasks =>
{
if (tasks[0].Exception != null)
{
tasks[0].Exception.Handle(exc =>
{
Console.WriteLine("First task failed :(");
return false; // signal that exception was handled, so it won't propagate
});
// add additional code here, or inside the Handle method above
}
if (tasks[1].Exception != null)
{
tasks[1].Exception.Handle(exc =>
{
Console.WriteLine("Second task failed :(");
return false; // signal that exception was handled, so it won't propagate
});
// add additional code here, or inside the Handle method above
}
// do the same for the rest of the tasks or iterate throught them with a foreach loop...
});