如何在Task.WhenAll上取消和引发异常(如果引发任何异常)? [英] How to cancel and raise an exception on Task.WhenAll if any exception is raised?
问题描述
我正在使用Task.WhenAll等待多次任务.当其中一个产生异常时,我希望Task.WhenAll(或其他等待多个任务的方式)立即取消其他任务并引发异常.
I am waiting on multiples task using Task.WhenAll. When one of them generates an exception I would like Task.WhenAll (or any other way of awaiting multiples tasks) to immediately cancel the others tasks and raise an exception.
有可能吗?
预先感谢
推荐答案
取消合作 WhenAll
不能取消线程,但是您可以将所有线程传递给CancellationToken
并在遇到异常时触发令牌.
Cancellation is coopertive the WhenAll
can't cancel the threads but you can pass all of them a CancellationToken
and fire the token when you get a exception.
CancellationTokenSource cts = new CancellationTokenSource();
var task1 = Func1Async(cts.Token);
task1.ContinueWith(task => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
var task2 = Func2Async(cts.Token);
task2.ContinueWith(task => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
var task3 = Func3Async(cts.Token);
task3.ContinueWith(task => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
await Task.WhenAll(task1, task2, task3);
在方法内部,您需要将token.ThrowIfCancellationRequested()
放在函数内部以检查令牌并取消任务
from inside the methods you will need to put token.ThrowIfCancellationRequested()
inside the functions to check the token and cancel the task
public async Task Func1Async(CancellationToken token)
{
foreach(var item in GetItems1())
{
await item.ProcessAsync(token);
token.ThrowIfCancellationRequested();
}
}
注意:您可以通过使用扩展方法来稍微整理一下代码
NOTE: You could clean up the code a bit by making a extension method
public static class ExtensionMethods
{
public Task CancelOnFaulted(this Task task, CancellationTokenSource cts)
{
task.ContinueWith(task => cts.Cancel(), cts.Token, taskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
return task;
}
public Task<T> CancelOnFaulted<T>(this Task<T> task, CancellationTokenSource cts)
{
task.ContinueWith(task => cts.Cancel(), cts.Token, taskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
return task;
}
}
这将使代码看起来像
CancellationTokenSource cts = new CancellationTokenSource();
var task1 = Func1Async(cts.Token).CancelOnFaulted(cts);
var task2 = Func2Async(cts.Token).CancelOnFaulted(cts);
var task3 = Func3Async(cts.Token).CancelOnFaulted(cts);
await Task.WhenAll(task1, task2, task3);
这篇关于如何在Task.WhenAll上取消和引发异常(如果引发任何异常)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!