编写一个 Task.WhenAll/WhenAny 变体,在第一个错误/取消的任务上取消所有其他任务 [英] Writing a Task.WhenAll/WhenAny variant that cancels all other tasks on first faulted/Cancelled task

查看:36
本文介绍了编写一个 Task.WhenAll/WhenAny 变体,在第一个错误/取消的任务上取消所有其他任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 C# 的新手,今天开始玩 TPL.我决定写一个修改过的版本Task Task.WhenAll 作为练习.我希望它具有以下行为:

I'm fairly new to C# and started playing around with the TPL today. I decided to write a modified version of Task Task.WhenAll as an exercise. I'd like for it to have the following behavior:

  • 找到第一个出错或被取消的任务后,取消其余任务,而不是等待它们完成.
  • 如果任务出错,返回的任务应该设置正确的异常(即没有吞咽并用 OperationCancelledException() 替换)
  • 方法签名中没有异步(希望避免冒泡).

我想出了以下疯狂/愚蠢的代码,但它不起作用,我很难想象发生了什么.我无法想象会发生任何阻塞,我预想发生的是一系列任务,每个任务都在等待其他任务完成.有人能解释一下这是怎么回事吗?

I came up with the following crazy/stupid piece of code that doesn't work and I am having a hard time visualizing what's going on. I can't imagine any blocking going on and what i envisioned happening was a chain of tasks each waiting on the rest for completion. Could someone explain what's going on?

我不会在生产代码中使用它,这只是为了测试我的基础知识.我意识到一种更简单的方法是执行 Task.WhenAll 并让列表中的任务本身具有在失败时取消的延续.

I wouldn't have it in production code and this is just to test my fundamentals. I realize an easier way of doing this would be to do a Task.WhenAll and have the tasks in the list themselves have continuations that do the cancellation on failure.

    public static Task WhenAllError(List<Task> tasks, CancellationToken ct)
    {
        var tcs = new TaskCompletionSource<object>();
        return Task.WhenAny(tasks).ContinueWith<Task>((t) =>
             {
                 if (tasks.Count == 0)
                 {
                     tcs.SetResult(null);
                     return tcs.Task;
                 }

                 if (t.IsFaulted)
                 {
                     Console.WriteLine("Task faulted. Cancelling other tasks: {0}", t.Id);
                     cts.Cancel();
                     // Make sure the tasks are cancelled if necessary
                     tcs.SetException(t.Exception);
                     return tcs.Task;
                 }
                 // Similarly handle Cancelled

                 tasks.Remove(t);
                 return WhenAllError(tasks, ct);
             }).Unwrap();
    }

推荐答案

CancellationToken 类没有 Cancel 方法.您需要一个 CancellationTokenSource 可以取消CancellationToken.

The CancellationToken class has no Cancel method. You need a CancellationTokenSource to be able to cancel the CancellationToken.

类似于影响任务的结果,你需要一个 TaskCompletionSource 你不能安全地取消已经运行的任务.请参阅此帖子

Similarly to affect the outcome of a task you need a TaskCompletionSource you can't safely cancel already running tasks. See this post

这篇关于编写一个 Task.WhenAll/WhenAny 变体,在第一个错误/取消的任务上取消所有其他任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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