2014-12-01 11 views
15

currenly mit dem folgenden Code für eine Sammlung von Aufgaben zu warten, zu vervollständigen. Ich habe jetzt jedoch eine Situation, in der ich den WhenAll-Anruf vorzugsweise über einen Storno-Token abbrechen/abbrechen möchte. Wie würde ich darüber gehen?Wie kann ich Task.WhenAll abbrechen?

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) 

Ich gehe davon aus, es wird aber etwas entlang der Linien des nächsten Stück Code, aber ich bin nicht sicher, was in ‚XXX‘ gehen würde.

Await Tasks.Task.WhenAny(Tasks.Task.WhenAll(TaskCollection), XXX) 
+3

Normalerweise würden Sie die eigentlichen Aufgaben selbst löschen. Sind Sie sicher, dass Sie das * Warten * für diese Aufgaben nur abbrechen möchten? –

+0

Es ist ein interessantes Problem. Ich hätte es nicht gelöst, wenn er nicht schon die meiste Antwort gehabt hätte. –

+0

@StephenCleary Ich habe ein Problem, wo eine der Aufgaben, der nicht abgeschlossen. Im Moment habe ich keine Ahnung warum. Ich brauche eine Ausfallsicherung, um WaitAll abzubrechen, wenn ich mich entscheide. Ich weiß, dass es die Aufgabe, die feststeckt, nicht löst, aber eine schnelle Lösung benötigt. Ich möchte das Hauptproblem beheben, aber ich habe eine große Codebasis und bin mir nicht sicher, wo es liegt. Ich kann hier aufgrund der Größe keinen vollständigen Code posten und kann auch keinen Code preisgeben, für den meine Kunden bezahlt haben. – iguanaman

Antwort

17

Verwenden TaskCompletionSource<T> eine Aufgabe für einige asynchronen Zustand zu schaffen, die nicht bereits eine asynchrone API hat. Verwenden Sie CancellationToken.Register, um das moderne CancellationToken-basierte Stornierungssystem in ein anderes Stornierungssystem einzubinden. Ihre Lösung muss nur diese beiden kombinieren.

Ich habe ein CancellationToken.AsTask() extension method in my AsyncEx library, aber Sie können Ihre eigene als solche schreiben:

<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 

Verwendung ist wie erwartet:

Await Task.WhenAny(Task.WhenAll(taskCollection), cancellationToken.AsTask()) 
+7

Eine Alternative für 'cancellationToken.AsTask()': 'Task.Delay (Timeout.Infinite, Token)'. – Noseratio

+0

Kennzeichnung dies als Antwort, wie es mir eine verknüpfte CancellationToken zu verwenden. – iguanaman

+0

Schönes Upgrade. Ich kann AsTask an mehreren Stellen sehen. –

3
Dim tcs as new TaskCompletionSource(Of Object)() 
Await Tasks.Task.WhenAny(Tasks.Task.WhenAll(TaskCollection), tcs) 

abzubrechen, rufen tcs.SetResult (Nothing). Dies wird Ihre Task.WhenAny auslösen.

0

Sie auch eine Verzögerung erwarten können:

await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(1000)); 
Verwandte Themen