编写Task.WhenAll / WhenAny变体,以取消第一个故障/已取消任务上的所有其他任务 [英] Writing a Task.WhenAll/WhenAny variant that cancels all other tasks on first faulted/Cancelled task
问题描述
我是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()吞噬) li>
- 方法签名中没有异步(希望避免冒泡)。
- Upon finding the first task that has faulted or been canceled, cancel the rest of the tasks instead of waiting for them to finish.
- If the task faulted, the returned task should have the right exception set (i.e no swallowing by continuation and replacing with OperationCancelledException())
- No async in the method signature (want to avoid bubbling it up).
我来了下面的疯狂/愚蠢的代码行不通,我很难想象发生了什么。我无法想象会发生什么阻碍,而我预想的是,一连串的任务都在等待其余的任务完成。
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屋!