我正在試驗如何跳出ForEachAsync回圈。break不起作用,但我可以呼叫CancelCancellationTokenSource。for 的簽名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();
}
uj5u.com熱心網友回復:
傳遞給呼叫的方法主體的令牌ForEachAsync是不同的,并且來自CancellationTokenSource將被取消的內部:
- 關于“外部”取消(這就是為什么你看到
t.IsCancellationRequested設定為何true時cts.Cancel()被呼叫) - 出于內部原因(我發現的一個原因 - 任何迭代都會引發未捕獲的例外)。
因此,cancellationToken CancellationToken傳遞給 的引數的目的Parallel.ForEachAsync是支持呼叫者取消以及傳遞給它呼叫的異步委托的引數 - 支持外部(即呼叫者)和內部源(參見 PS)的取消。
聚苯乙烯
另請注意,通常最好在您的方法中傳遞和檢查令牌狀態(即await someConditionAsync(t)內部具有相應的實作),因為CancelationToken它用于所謂的合作取消。
uj5u.com熱心網友回復:
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://www.uj5u.com/qita/370996.html
