2012-11-29 14 views
5

Mam różne zadania do odczytania z różnych plików i znaleźć słowo do nich. Włożyłem je do tablicy zadań, które Zacznę metody waitAny następująco:Jak zatrzymać wszystkie zadania po zakończeniu C#

foreach (string file in filesList) 
     { 
      files[i] = Task.Factory.StartNew(() => 
      { 
       mySearch.Invoke(file); 
      }); 
      i++; 
     } 
     System.Threading.Tasks.Task.WaitAny(files); 

Chciałbym zatrzymać wszystkie inne zadania, jak tylko jedno z zadań kończy (to kończy, gdy zakłada słowo). W tej chwili, dzięki waitany, mogę wiedzieć, kiedy kończy się jedno zadanie, ale nie wiem, jak mogłem się dowiedzieć, który z nich się zakończył i jak zatrzymać inne zadania. Jaki byłby najlepszy sposób, aby to osiągnąć?

+0

Czy wykonane zadanie pozostawia gdzieś wynik? Może to obejmować identyfikację zadania. Pierwsze zadanie do wykonania może również ustawić zdarzenie, sprawdzane przez każde zadanie w pętli głównej, które spowoduje zakończenie wszystkich innych zadań. – HABO

+0

w mySearch.Invoke, ich pętla powinna być iteracją po słowie. Następnie można dodać flagę tak, aby pętla uległa awarii, gdy flaga jest sygnalizowana, gdy dowolne zadanie znajdzie słowo, możesz zasygnalizować flagę – ComfortablyNumb

Odpowiedz

2

Możesz użyć pojedynczej CancellationToken, którą wszystkie zadania zostaną udostępnione. Wewnątrz metody mySearch.Invoke sprawdź wartość token.IsCancellationRequested, aby anulować zadanie. Gdy niektóre zadania zostaną zakończone, anuluj inne za pomocą CancellationTokenSource.Cancel().

var tokenSource = new CancellationTokenSource(); 
var token = tokenSource.Token; 

foreach (string file in filesList) 
{ 
    // pass cancellation token to your task 
    files[i] = Task.Factory.StartNew(() => mySearch.Invoke(file, token), token); 
    i++; 
} 

Task.WaitAny(files); 
tokenSource.Cancel(); 

BTW można wymusić żeton rzucać OperationCanceledException kiedy źródłem jest anulowana przez wywołanie token.ThrowIfCancellationRequested()

2

Podczas tworzenia zadania można przekazać CancelationToken. Ustaw ten token, gdy zakończy się jedno z zadań. Spowoduje to pozostanie zadań z tym tokenem do not execute. Uruchomione zadania mogą otrzymać OperationCanceledException i zatrzymać się.

1

Gorąco polecam czytanie How do I cancel non-cancelable async operations? przez Stephena Touba. Zasadniczo musisz anulować wszystkie te zadania, ale obecnie nie masz mechanizmu ich anulowania.

Idealne podejście polegałoby na stworzeniu CancellationTokenSource przed foreach, przekazaniu CancellationToken z tego źródła do każdego z zadań podrzędnych, sprawdzanie tego tokenu okresowo i zaprzestanie wykonywania pracy, gdy zauważysz, że jest to anulowane. Następnie możesz anulować źródło tokena w kontynuacji WhenAny.

Jeśli to nie jest opcja, musisz zdecydować, czy ważne jest, aby rzeczywiście zatrzymać wykonywanie zadań (co, na prawdę, nie może być zrobione), czy po prostu kontynuować kod bez oczekiwania na ich zakończenie (łatwo to zrobić).