.NET 6 Parallel.ForEachAsync 中需要两个取消令牌吗?

Vic*_*c F 4 c# cancellation cancellation-token parallel.foreachasync

我正在尝试如何打破循环ForEachAsyncbreak不起作用,但我可以调用CancelCancellationTokenSource。的签名ForEachAsync有两个标记 - 一个作为独立参数,另一个在Func主体签名中。

我注意到,当cts.Cancel()调用时,tokent变量都IsCancellationRequested设置为 true。所以,我的问题是:这两个单独的论点的目的是什么token?有什么值得注意的区别吗?

List<string> symbols = new() { "A", "B", "C" };
var cts = new CancellationTokenSource();
var token = cts.Token;
token.ThrowIfCancellationRequested();

try
{
    await Parallel.ForEachAsync(symbols, token, async (symbol, t) =>
    {
        if (await someConditionAsync())
        {
            cts.Cancel();
        }
    });
catch (OperationCanceledException oce)
{
    Console.WriteLine($"Stopping parallel loop: {oce}");
}
finally
{
    cts.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

Gur*_*ron 7

传递给调用方法主体的令牌ForEachAsync是不同的,并且来自CancellationTokenSource将被取消的内部:

  • 关于“外部”取消(这就是为什么您看到t.IsCancellationRequested设置为“true何时cts.Cancel()被调用”)
  • 出于内部原因(我发现的一个原因 - 任何迭代都会引发未捕获的异常,即应用快速失败原则)。

cancellationToken CancellationToken因此,传递给 的参数的目的Parallel.ForEachAsync是支持调用者的取消,以及传递给它调用的异步委托的参数的目的 - 支持外部(即调用者)和内部源的取消(请参阅 PS)。

聚苯乙烯

另请注意,通常最好在方法中传递和检查令牌状态(即await someConditionAsync(t)内部有相应的实现),因为CancelationToken用于所谓的合作取消