2014-12-29 11 views
5

Od kiedy zrozumiałem Task w kontekście zagnieżdżonego zadania, naprawdę tego nie rozumiem- Dlaczego trzeci wydruk przed drukiem?Zadanie rodzica Task.ContinueWith() nie czeka na zakończenie zadania potomnego

Mimo, Użyłem Task.WaitAll(t), drukować 3rd linię przed linii.

Kod:

public static void Main() 
     { 

      Task t = new Task(
       () => 
       { 
        Thread.Sleep(2000); 
        Console.WriteLine("1st print..."); 
       }); 
      t.ContinueWith(
       x => 
       { 
        Thread.Sleep(2000); 
        Console.WriteLine("2nd print..."); 
       }, 
       TaskContinuationOptions.OnlyOnRanToCompletion); 

      t.Start(); 
      Task.WaitAll(t); 

      Console.WriteLine("3rd print..."); 
      Console.Read(); 

} 

wyjściowa:

enter image description here

+0

produkować ten sam wynik, nawet jeśli używam „TaskContinuationOptions.AttachedToParent” z opcją zadania należy dziecka. – nunu

+0

@Andrey Oczywiście mamy podwójne pytanie, ale odpowiedź na to podwójne pytanie polega na utworzeniu tablicy zadań Task [], która jest rozwiązaniem, które znam. Ale chcę znać odpowiedź bez tworzenia tablicy Zadanie []. – nunu

+0

Chcę korzystać z mojego samochodu, aby jechać do miejsc bez wpuszczania na niego gazu, ale się nie ruszy! – Jcl

Odpowiedz

5

Trzeba czekać na kontynuację także:

Task t2 = t.ContinueWith(/* .. */); 
Task.WaitAll(new [] { t, t2 }); 
+0

Dzięki @Jcl! ALE, nie chcę tworzyć wielu zadań. Chcę to obsłużyć jednym zadaniem. Oczywiście możemy tworzyć zadania zagnieżdżone w ramach jednego zadania nadrzędnego jako zadania podrzędne, ale NIE w zupełnie innym zadaniu. – nunu

+3

Używasz 'ContinueWith', więc już tworzysz drugie zadanie ... po prostu nie przechowujesz wyniku funkcji' ContinueWith', ale to nie znaczy, że zadanie nie jest tworzone. – Jcl

2

Wystarczy tylko czekał na t, nie dla jego kontynuacji. Dlatego ta kontynuacja potrwa jakiś czas w przyszłości. Jeśli nie byłby dla Console.Read, może nigdy nie zostać uruchomiony przed zakończeniem procesu.

Task.WaitAll(t) jest odpowiednikiem t.Wait() (którego należy użyć zamiast tego, ponieważ jest bardziej idiomatyczny).

Oczekiwanie na wszystkie kontynuacje (może rekursywnie) spowodowałoby nieintuicyjne zachowanie i miało nielokalne skutki. Zdalne części programu mogą wpływać na twój kod.

+0

Dzięki @usr! Teraz pytanie brzmi: jak mam czekać na zakończenie zadania zagnieżdżonego? – nunu

+0

Przechowuj to zadanie gdzieś, a także czekaj na niego. – usr

0

Przyjmujesz założenie, że powinien on czekać na zadania podrzędne, ale nie ma podstaw, aby takie założenia przyjąć. Od MSDN:

Task.WaitAll: Czeka na wszystkie dostarczone obiekty zadań, aby zakończyć wykonywanie .

I robi dokładnie to, co mówi. Numer ContinueWith nie zmienia długości oryginalnego zadania, nie staje się dłuższy. Wykonuje się zaraz po.