2014-12-29 5 views
5

Поскольку я понимал Task в контексте вложенной задачи, я действительно этого не понимаю. Почему 3-й вывод перед 2-й печатью?Task.ContinueWith() родительская задача не ждет завершения дочерней задачи

Даже если я использовал Task.WaitAll(t), распечатать 3-й строку перед линии.

Код:

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(); 

} 

Выход:

enter image description here

+0

Это тот же результат, даже если я использую «TaskContinuationOptions.AttachedToParent» с опцией дочерней задачи. – nunu

+0

@ Andrey Конечно, у нас есть дублированный вопрос, но ответ на этот дублирующий вопрос основан на создании массива задач Task [], который является тем решением, которое я знаю. Но я хочу знать ответ, не создавая массив Task []. – nunu

+0

Я хочу использовать свой автомобиль, чтобы идти в места, не ставя на него газ, но он не движется! – Jcl

ответ

5

Вы должны ждать продолжения также:

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

Спасибо @Jcl! НО, я не хочу создавать несколько задач. Я хочу справиться с этим с помощью одной задачи. Конечно, мы можем создавать вложенные задачи в одной родительской задаче как дочерние задачи, но НЕ совсем другую задачу. – nunu

+3

Вы используете 'ContinueWith', так что вы уже создаете вторую задачу ... вы просто не сохраняете результат функции' ContinueWith', но это не значит, что задача не создана. – Jcl

2

Вы только ждали t, а не для ее продолжения. Вот почему это продолжение продолжится в будущем. Если бы он не был для Console.Read, он никогда не запустится до выхода процесса.

Task.WaitAll(t) эквивалентен t.Wait() (который следует использовать вместо этого, поскольку он более идиоматический).

Ожидая, что все продолжения (возможно, рекурсивно) повлияют на неинтуитивное поведение и будут иметь нелокальные эффекты. Удаленные части программы могут повлиять на ваш код.

+0

Спасибо @usr! Теперь вопрос в том, как я могу дождаться завершения вложенной задачи? – nunu

+0

Храните эту задачу где-нибудь и ждите ее. – usr

0

Вы делаете предположение, что он должен ждать дочерних задач, но нет оснований делать такие предположения. От MSDN:

Task.WaitAll: ожидает выполнения всех заданных объектов задачи выполнение.

И он делает именно то, что он говорит. ContinueWith не изменяет длину исходной задачи, она не увеличивается. Сразу после этого.

Смежные вопросы