我正在使用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上取消和引发异常(如果引发任何异常)?
发布评论