引擎盖下的 WaitAny 和 WaitAll 等待算法(检查任务的顺序)

WaitAny and WaitAll waiting algorithms under the hood (order of check tasks)

我需要用 general/simple 术语理解等待方法(Task.WaitAnyTask.WaitAll)等待任务完成的算法。我不太了解这种语言,无法深入研究源代码。我试过了,但我完全糊涂了。我已经到了两种方法都可以调用方法 AddCompletionAction 的地步。

对我来说,这是多余的信息,我希望根据算法得到一个简单的答案。

问题一般来说,如何在指定的方法中检查任务的完成情况?

例如:

WaitAny 检查每个任务的 IsCompleted 并延迟时间,当任何任务的 IsCompleted 为真时,该方法退出。

WaitAll 会延迟检查每个任务的 IsCompleted,当 IsCompleted 为真时,此任务将从以下检查中排除。或者 WaitAll 有条件地检查第一个任务的 IsCompleted,直到 IsCompleted 为假,否则不会检查其他任务。

这些都是我的猜测,我很难弄清楚框架的源代码。 就像我写的那样,需要用简单的词来回答。不需要描述整个方法的操作,影响取消令牌等等。只对检查任务的顺序感兴趣。

基本前提是两种方法都循环遍历 Task 列表并为每个 Task 分配一个完成触发器 - 它会记录有多少项目达到了完成触发器。

这是您找到两者之间差异的地方 - 如果它是 WaitAny 则第一次触发完成触发器(即 Task 恰好完成最快);它 returns 并返回到任何称为 WaitAny.

的方法

WaitAll 只有 returns 一旦完成的 Task 的计数与传入方法的原始 Task 的计数相匹配。

您搞错了 - 它不是间歇性地检查是否完成;它在等待它。与赛车类似,终点线并不是间歇性地检查是否有东西越过它 - 有一根横梁穿过它,当有人越过终点线时,他们会打断横梁,而横梁被打断会触发 lap/race 完成过程。

我将尝试用简单的代码而不是简单的文字来回答您的问题。以下是 WaitAnyWaitAll 这两种方法如何由了解基本机制但对正确获取细节完全漠不关心的人实施:

// For demonstration purposes only. This code is rubbish.
static Task MyWaitAny(params Task[] tasks)
{
    var tcs = new TaskCompletionSource<Task>();
    foreach (var task in tasks)
    {
        task.ContinueWith(t => tcs.SetResult(t));
    }
    return tcs.Task.Result;
}

// For demonstration purposes only. This code is rubbish.
static void MyWaitAll(params Task[] tasks)
{
    var tcs = new TaskCompletionSource();
    int completedCount = 0;
    foreach (var task in tasks)
    {
        task.ContinueWith(t =>
        {
            completedCount++;
            if (completedCount == tasks.Length) tcs.SetResult();
        });
    }
    tcs.Task.Wait();
}

MyWaitAny 首先创建一个 TaskCompletionSource<Task>。这是将传播首先完成的 Task 的机制。然后在 tasks 中的每个 Task 附加一个延续。此延续立即完成 TaskCompletionSource<Task>. Finally the Task property of the TaskCompletionSource<Task> is waited by invoking the Result.

MyWaitAll 首先创建一个 TaskCompletionSource. This mechanism will not propagate anything. It is created just for the purpose of waiting its Task property. Then a continuation is attached to each Task in the tasks. This continuation increments a counter, and when the counter reaches the tasks.Length it means that all tasks are completed, and so the TaskCompletionSource is completed too. Finally the Task property of the TaskCompletionSource is waited by invoking the Wait

注意: 请注意,上面的代码与 production-ready 相去甚远,甚至都不好笑。如果您对修复它有任何诱惑,请不要。您可能能够解决六个问题,许多其他问题仍然存在。