Как я могу отменить Task.WhenAll?
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)
Я предполагаю, что это произойдет, но что-то похожее на следующий бит кода, но я не уверен, что будет в XXX.
Await Tasks.Task.WhenAny(Tasks.Task.WhenAll(TaskCollection), XXX)
Ответы
Ответ 1
Используйте 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
Использование, как и ожидалось:
Await Task.WhenAny(Task.WhenAll(taskCollection), cancellationToken.AsTask())
Ответ 2
Dim tcs as new TaskCompletionSource(Of Object)()
Await Tasks.Task.WhenAny(Tasks.Task.WhenAll(TaskCollection), tcs)
Чтобы отменить, вызовите tcs.SetResult(Nothing). Это запустит вашу Task.WhenAny.
Ответ 3
Вы также можете ожидать задержки:
await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(1000));