2014-02-18 102 views
6

因此,這裏是我的代碼父任務不會等待子任務完成

Task<int[]> parent = Task.Run(() => 
{ 
    var result = new int[3]; 

    TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously); 

    for (int i = 0; i < result.Length; i++) 
    { 
     int j = i; 
     tf.StartNew(() => result[j] = GetRandomNumber(j)); 
    } 

    return result; 
}); 

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

finalTask.Wait(); 

基本上我創建3個Task S的是Task稱爲父(我猜)的兒童。我不重視父任務,等待所有三個子任務完成。之後finalTask將由於finalTask.Wait();這個語句等待執行。但事情並不像預期的那樣發生。我的意思是應用程序在任何GetRandomNumber調用完成之前退出。這裏的代碼的一部分是從書中複製的,它指出那些父任務應該等待子任務完成,這顯然沒有發生。我在這裏錯過了什麼嗎?

這是getRandomNumber的呢

public static int GetRandomNumber(int ii) 
{ 
    Random rand = new Random(); 

    for (int i = 0; i < 1000000000; i++) { } // imitate some jobs 

    return rand.Next(1000); 
} 

此代碼做同樣的事情

Task<int[]> parent = Task.Run(() => 
{ 
    var result = new int[3]; 

    for (int i = 0; i < result.Length; i++) 
    { 
     int j = i; 
     new Task(() => result[j] = GetRandomNumber(j), TaskCreationOptions.AttachedToParent).Start(); 
    } 

    return result; 
}); 
+0

這只是一個例子。 – Dimitri

+0

單步執行代碼,看看它在做什麼。 – SQLMason

+0

GetRandomNumber被命中3次,但該方法的結束從未被擊中 – Dimitri

回答

12

此行爲是由於您使用Task.Run方法,它被連接到母禁止子任務:

Run方法是將StartNew方法的簡單的選擇。它創建一個任務[其] CreationOptions屬性值爲TaskCreationOptions.DenyChildAttach

要解決,只是您的第一線,從

Task<int[]> parent = Task.Run(() => 

改變

Task<int[]> parent = Task.Factory.StartNew(() => 
+0

就是這樣,你明白了。謝謝 ;) – Dimitri

8

Task.Run的文檔,你會發現,它指定

其CreationOptions屬性值是TaskCreationOptions.DenyChildAttach。

因此,即使您指定TaskCreationOptions.AttachedToParent,它也會被忽略。

+0

我正準備發佈這個可以讓它相同的內容:http://social.msdn.microsoft.com/Forums/vstudio/en-US/ 6e142b15-0e41-4cbc-bccc-bb7bdebe0795/how-does-taskcreationoptionsattachedtoparent-work-on-task-hierarchy?forum = parallelextensions – SQLMason

1

請使用如下代碼:

static void RunParentTask() 
    { 
     Task<int[]> parent = Task.Factory.StartNew<int[]>(() => 
     { 
      var results = new int[3]; 

      TaskFactory<int> factory = new TaskFactory<int>(TaskCreationOptions.AttachedToParent, 
                  TaskContinuationOptions.ExecuteSynchronously); 
      factory.StartNew(() => results[0] = 1); 
      factory.StartNew(() => results[1] = 2); 
      factory.StartNew(() => results[2] = 3); 

      return results; 
     }); 

     parent.Wait(); 

     foreach (var item in parent.Result) 
     { 
      Console.WriteLine(item); 
     } 
    }