2013-11-15 3 views
2

Насколько я понимаю, метод ContinueWith ждет завершения заданий. В случае следующего кода это означает, что он закончен, когда он выполняется с его дочерними задачами. Если это так, то почему оно иногда выводится 0 0 0 и в других случаях 0 1 2?Почему дочерние задачи не заканчиваются раньше. Продолжение?

static void Main(string[] args) 
    { 

     Task<Int32[]> parent = Task.Run(() => 
      { 
       var results = new Int32[3]; 
       new Task(() => results[0] = 0, TaskCreationOptions.AttachedToParent).Start(); 
       new Task(() => results[1] = 1, TaskCreationOptions.AttachedToParent).Start(); 
       new Task(() => results[2] = 2, TaskCreationOptions.AttachedToParent).Start(); 

       return results; 
      }); 

     var finalTask = parent.ContinueWith(n => 
     { 
      foreach (Int32 i in n.Result) 
       Console.WriteLine(i); 
     }); 

     finalTask.Wait(); 

     Console.ReadLine(); 

    } 
+0

@HansPassant: На поверхности он выглядит как ребенок задачи привязаны к родителю поэтому родитель не будет завершен до тех пор, пока у детей не будет. Таким образом, OP написал код, который предназначен для правильного использования 'ContinueWith'. Проблема в том, что он не выбрал ожидаемое исключение, когда дочерние задачи не подключались к родительскому элементу. Незначительные изменения кода прекрасно в состоянии получить желаемый результат, не касаясь 'ContinueWith'. – Chris

ответ

2

От http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx

При передаче Действие на Task.Run:

Task.Run(someAction);

это точно эквивалентно:

Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

Это похоже на то, что он будет останавливать детей от прикрепления, как ожидалось.

Действительно изменения линии старта до

Task<Int32[]> parent = Task.Factory.StartNew(() => 

, похоже, чтобы исправить эту проблему. Я пришел к такому выводу, посмотрев, что они сделали по-другому на http://msdn.microsoft.com/en-us/library/dd997417(v=vs.110).aspx, который использует метод Factory.StartNew вместо Run.

Сказав, что я не знаю, почему он не бросать InvalidOperationException при попытке присоединить задачи ...

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