我正在试验如何打破ForEachAsync循环。break不工作,但我可以在CancellationTokenSource上调用Cancel。ForEachAsync的签名有两个令牌-一个作为独立参数,另一个在Func主体签名中。
我注意到,当调用cts.Cancel()时,token和t变量都将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();
}发布于 2021-12-01 21:47:35
传递给ForEachAsync调用的方法主体的令牌是一个不同的标记,来自将被取消的内部CancellationTokenSource:
cts.Cancel()时看到t.IsCancellationRequested设置为true的原因)因此,传递给cancellationToken CancellationToken的Parallel.ForEachAsync参数的目的是支持调用方的取消,以及传递给它调用的异步委托的取消--支持外部(即调用方)和内部源(参见P.S.)的取消。
附注:
还请注意,通常传递和检查方法中的令牌状态是个好主意(例如,await someConditionAsync(t)中有相应的实现),因为CancelationToken用于所谓的协同取消。
发布于 2021-12-01 21:48:11
Parallel.ForEachAsync接受一个令牌,您可以使用它取消for-each (函数的输入),该令牌也传递给for-each的每一次迭代(向lambda输入)。
将取消令牌传递给lambda的原因之一是避免捕获位于lambda表达式之外的变量。
想象一下这段代码:
await Parallel.ForEachAsync(symbols, token, async (symbol, t) => MyCode(symbol, t));
Task async MyCode(string symbol, CancellationToken token)
{
if (await someConditionAsync())
{
cts.Cancel();
}
});以这种方式编写,MyCode没有访问token的权限。
使用lambda意味着可以“继承”lambda之外的变量,但这并不意味着您应该继承。
https://stackoverflow.com/questions/70191295
复制相似问题