如何在Task.WhenAll上取消和引发异常(如果引发任何异常)? [英] How to cancel and raise an exception on Task.WhenAll if any exception is raised?

查看:209
本文介绍了如何在Task.WhenAll上取消和引发异常(如果引发任何异常)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆