2011-01-12 10 views
9

Prawie cała dokumentacja, którą widziałem przy korzystaniu z C# 4.0 Task.Factory.StartNew stwierdza, że ​​aby poczekać na zakończenie zadania, musisz poczekać. Ale moje wstępne testy pokazują, że jest to niepotrzebne. Czy ktoś inny może mi to potwierdzić? Ciekawi mnie, dlaczego tak wiele odniesień online i drukowanych mówi, że powinieneś zadzwonić do Wait.Czy funkcja Wait() jest konieczna po użyciu Task.Factory.StartNew()?

Oto prosta aplikacja konsolowa, która pokazuje, że nie potrzebuję oświadczenia Oczekiwanie, więc skomentowałem to. Niezależnie od tego, czy komentuję tsk.Wait(), dane wyjściowe są takie same.

Oczekiwana moc we wszystkich przypadkach jest następująca:

 
Main thread starting. 
After running MyTask. The result is True 
After running SumIt. The result is 1 
Main thread ending. 

Kod:

class Program 
{ 
    // A trivial method that returns a result and takes no arguments. 
    static bool MyTask() 
    { 
     Thread.Sleep(2000); 
     return true; 
    } 

    // This method returns the summation of a positive integer 
    // which is passed to it. 
    static int SumIt(object v) 
    { 
     int x = (int)v; 
     int sum = 0; 
     for (; x > 0; x--) 
      sum += x; 
     return sum; 
    } 

    static void Main(string[] args) 
    { 
     Console.WriteLine("Main thread starting."); 
     // Construct the first task. 
     Task<bool> tsk = Task<bool>.Factory.StartNew(() => MyTask()); 
     // I found this Wait statement to be completely unnecessary. 
     //tsk.Wait(); 
     Console.WriteLine("After running MyTask. The result is " + 
     tsk.Result); 
     // Construct the second task. 
     Task<int> tsk2 = Task<int>.Factory.StartNew(() => SumIt(1)); 
     Console.WriteLine("After running SumIt. The result is " + 
     tsk2.Result); 
     tsk.Dispose(); 
     tsk2.Dispose(); 
     Console.WriteLine("Main thread ending."); 
     Console.ReadLine(); 
    } 
} 

Odpowiedz

19

Jeśli chcesz tylko poczekać na zakończenie zadania, zaleca się zadzwonić pod numer .Wait(). Dla Task (w przeciwieństwie do Task<T>) jest to jedyna opcja.

Dla Task<T>, jednak istnieje również .Result, co także czeka, a to jest to, czego używasz. W twoim przypadku nie trzeba dzwonić pod numer .Wait().

+0

Dzięki, Timwi. Miałem bicie mózgu i nie zauważyłem, że używam Zadanie zamiast Zadanie. Teraz to ma sens! –

+0

@tambui: jak oznaczyć to jako odpowiedź? – stackoverflowuser

+0

@stackoverflowuser: Przepraszam, nie wiedziałem, jak to zrobić. Zrobione teraz. –

1

Ponieważ według this, uzyskiwania dostępu do Value z Task gwarantuje, że zadanie zostanie zakończone, ty” na pewno nie jest to wymagane.

+0

Zgadza się. Dzięki, Jacob! Mój błąd polegał na tym, że zapomniałem, że używam Zadanie zamiast Zadanie. –

1

Jak stwierdził Timwi, .Rezult również czeka. Ponieważ używasz komendy tsk.Result w wywołaniu Console.WriteLine, robisz oczekiwanie jako efekt uboczny.

Zależy również od czasu wykonania zadania. Jeśli jest bardzo krótki, możesz nie zdawać sobie sprawy z potrzeby. Czekamy, ponieważ wydaje się, że zawsze kończy się czas. Istnieje niebezpieczeństwo opuszczenia go, jeśli zadanie będzie wymagało ukończenia przed kontynuowaniem. Z tego powodu powinno się używać .a nawet 99% czasu, w rzeczywistości nie jest to czas oczekiwania.

2

Jedną ważną cechą obiektu Wait jest to, że działa on jako punkt spotkania, ponieważ każdy wyjątek wygenerowany przez Task zostanie ponownie przesłany w tym momencie. Ponieważ obecna implementacja Task wymusza przestrzeganie takiego wyjątku, jest dobrym rozwiązaniem. Możesz jednak również zaobserwować wyjątek, wysyłając zapytanie do instancji Task o wyjątek.

*) Najwyraźniej zostanie to zmienione. Zachowanie zostało zmienione w Async CTP.

Powiązane problemy