当某些任务可能被取消时等待多个任务
Waiting for multiple tasks when some might be cancelled
我正在尝试等待多个任务,我预计其中一些可能会被取消。我使用 问题作为灵感来源,让 WhenAll
相应地处理取消的任务...
但是,如果 none 的任务被取消,这也会引发异常!
var source = new CancellationTokenSource();
var task1 = Task.Delay(100, source.Token);
source.Cancel();
var task2 = Task.Delay(300);
await Task.WhenAll(task1, task2).ContinueWith(_ => { }, TaskContinuationOptions.OnlyOnCanceled);
在上面的例子中,如果 source.Cancel()
没有被执行,那么最终的 await
将抛出异常。我可以通过从最后一行中删除 ContinueWith
来解决这个问题,但是如果任务被取消,WhenAll
将失败并出现相同的错误。
当其中一些任务可能(但不一定)被取消时,等待任务列表的正确做法是什么?
我认为问题是 TaskContinuationOption
你通过了。在您的示例中,您使用 OnlyOnCanceled
。所以只有在任务被取消时它才会继续。
我不确定取消任务时所需的行为是什么。如果您只想在 none 个被取消时继续,您可以使用 NotOnCanceled
。如果您想在任何一种情况下继续,是否取消任务,那么您可以使用 NotOnFaulted
,因为取消不被视为错误。
ContinueWith
是一个primitive方法,一般不适合应用代码。将它与 await
混合使用就更不可取了,因为那样你就可以使用两种语义略有不同的不同机制来实现相同的目标。你的例子暗示你想忽略由 CancellationTokenSource
的取消引起的异常。我的建议是 catch
这些异常并忽略它们。
var cts = new CancellationTokenSource(100);
var task1 = Task.Delay(200, cts.Token);
var task2 = Task.Delay(300);
try
{
await Task.WhenAll(task1, task2);
}
catch (OperationCanceledException) { } // Ignore cancellation exceptions
您可以使用 when
上下文关键字更加具体,以避免忽略由未知 CancellationTokenSource
s:
引起的异常
catch (OperationCanceledException ex) when (ex.CancellationToken == cts.Token) { }
虽然这可能会产生不同的问题,因为方法可能会将提供的 CancellationToken
包装到 linked CancellationTokenSource
中,在这种情况下 catch
/when
可能无法处理由已知令牌发起的 OperationCanceledException
。
我正在尝试等待多个任务,我预计其中一些可能会被取消。我使用 WhenAll
相应地处理取消的任务...
但是,如果 none 的任务被取消,这也会引发异常!
var source = new CancellationTokenSource();
var task1 = Task.Delay(100, source.Token);
source.Cancel();
var task2 = Task.Delay(300);
await Task.WhenAll(task1, task2).ContinueWith(_ => { }, TaskContinuationOptions.OnlyOnCanceled);
在上面的例子中,如果 source.Cancel()
没有被执行,那么最终的 await
将抛出异常。我可以通过从最后一行中删除 ContinueWith
来解决这个问题,但是如果任务被取消,WhenAll
将失败并出现相同的错误。
当其中一些任务可能(但不一定)被取消时,等待任务列表的正确做法是什么?
我认为问题是 TaskContinuationOption
你通过了。在您的示例中,您使用 OnlyOnCanceled
。所以只有在任务被取消时它才会继续。
我不确定取消任务时所需的行为是什么。如果您只想在 none 个被取消时继续,您可以使用 NotOnCanceled
。如果您想在任何一种情况下继续,是否取消任务,那么您可以使用 NotOnFaulted
,因为取消不被视为错误。
ContinueWith
是一个primitive方法,一般不适合应用代码。将它与 await
混合使用就更不可取了,因为那样你就可以使用两种语义略有不同的不同机制来实现相同的目标。你的例子暗示你想忽略由 CancellationTokenSource
的取消引起的异常。我的建议是 catch
这些异常并忽略它们。
var cts = new CancellationTokenSource(100);
var task1 = Task.Delay(200, cts.Token);
var task2 = Task.Delay(300);
try
{
await Task.WhenAll(task1, task2);
}
catch (OperationCanceledException) { } // Ignore cancellation exceptions
您可以使用 when
上下文关键字更加具体,以避免忽略由未知 CancellationTokenSource
s:
catch (OperationCanceledException ex) when (ex.CancellationToken == cts.Token) { }
虽然这可能会产生不同的问题,因为方法可能会将提供的 CancellationToken
包装到 linked CancellationTokenSource
中,在这种情况下 catch
/when
可能无法处理由已知令牌发起的 OperationCanceledException
。