如何取消Task.WhenAll?

igu*_*man 18 .net vb.net task-parallel-library

Currenly使用以下代码等待完成任务的集合.但是,我现在有一种情况,我希望能够通过取消令牌取消/中止WhenAll调用.我该怎么办呢?

  Dim TaskCollection As New List(Of Tasks.Task)
  For x As Integer = 1 To Threads
    Dim NewTask As Tasks.Task = TaskHandler.Delegates(DelegateKey).Invoke(Me, Proxies, TotalParams).ContinueWith(Sub() ThreadFinished())
    TaskCollection.Add(NewTask)
  Next

  Await Tasks.Task.WhenAll(TaskCollection)
Run Code Online (Sandbox Code Playgroud)

我假设它会接下来的代码,但是我不确定'XXX'中会出现什么.

Await Tasks.Task.WhenAny(Tasks.Task.WhenAll(TaskCollection), XXX)
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 20

使用TaskCompletionSource<T>创造不已经有一个异步API一些异步状态的任务.用于CancellationToken.Register将现代基于CancellationToken的取消系统挂钩到另一个取消系统.您的解决方案只需要将这两者结合起来.

我的CancellationToken.AsTask()AsyncEx库中有一个扩展方法,但您可以自己编写:

<System.Runtime.CompilerServices.Extension> _
Public Shared Function AsTask(cancellationToken As CancellationToken) As Task
  Dim tcs = New TaskCompletionSource(Of Object)()
  cancellationToken.Register(Function() tcs.TrySetCanceled(), useSynchronizationContext := False)
  Return tcs.Task
End Function
Run Code Online (Sandbox Code Playgroud)

用法如您所愿:

Await Task.WhenAny(Task.WhenAll(taskCollection), cancellationToken.AsTask())
Run Code Online (Sandbox Code Playgroud)

  • `cancellationToken.AsTask()`的替代方法:`Task.Delay(Timeout.Infinite,token)`. (11认同)
  • @Leonardo:我在 AsyncEx 中有一个 `Task.WaitAsync(CancellationToken)` 扩展方法,我现在建议用于取消等待。所以这些天我会推荐“await Task.WhenAll(taskCollection).WaitAsync(cancellationToken)”。 (3认同)
  • 当任务没有取消时怎么办?您无法处置它。它永远不会完成。在我的代码中,我将其启动次数与用户单击的次数一样多。用户的每次点击都会创建一个永远不会完成的任务。如果我请求取消令牌,但这会破坏我的代码流,因为稍后会使用此令牌来测试在操作未取消时是否需要执行其他操作。 (2认同)
  • @哈里:你不应该创建永远无法完成的任务。有关现代方法,请参见[`AsyncEx.Tasks`](https://github.com/StephenCleary/AsyncEx.Tasks)中的`Task.WaitAsync`。 (2认同)
  • @StephenCleary 这个答案现在已经过时,并且您库中的代码已过时或已删除。我今天如何取消“Task.WhenAll”?也许没有你的(预发布)库,也没有内存泄漏。 (2认同)