2010-07-28 92 views
0

我正在使用.NET新的TPL庫,並面對一些我無法解釋的奇怪行爲。出於某種原因,嵌套任務不會在我的情況下啓動。我簡化了我的解決方案:任務並行庫。嵌套任務無法啓動

 bool flag = false; 

     for (int i = 0; i < 5; i++) 
     { 
      Task.Factory.StartNew(() => 
         { 
          while (true) // a lot of newcoming tasks 
          { 
           Thread.Sleep(200); //do some work 
           Task.Factory.StartNew(() => 
              { 
               flag = true; 
               }); 
          } 
         }); 
     } 

     Thread.Sleep(2000); 
     Assert.IsTrue(flag); 

我有5個同時運行的任務。每個任務從暫掛隊列中檢索一些元素,執行一些操作,然後嘗試爲此操作的結果運行嵌套任務。問題是,如果有太多的元素(while(true)模擬這個),並且所有5個任務都在不斷運行嵌套任務不會啓動。只能在while循環完成其大部分任務後才能啓動。

這似乎有點問題,而語句塊嵌套任務運行,但我不知道是什麼:)

回答

3

Task.Factory.StartNew不啓動任務,它將任務添加到要調度的任務列表中,並且調度程序可以根據事情來決定何時運行該任務;可用核心數量(線程池大小),當前CPU負載以及現有工作的吞吐量。起

http://parallelpatterns.codeplex.com/releases/view/48562

頁的PDF的63:

你應該瞭解這裏的任務調度的部分。

LongRunning選項通過完全繞過線程池來「修復」您的問題。這有一些缺點,它會允許你創建比你的系統真正使用的更多的線程,這會導致過度的上下文切換而降低性能。

類似上面使用線程睡眠的代碼的實驗是誤導性的,因爲它們「欺騙」了調度程序。它看到它增加了更多的工作,但CPU負載卻沒有增加.63你應該用一個包含數學的緊密循環來代替睡眠(例如計算Sqrt())

爲什麼不簡單地只有一個外層。環路從隊列中讀取項目,並執行他們的任務,這樣你的應用程序將最大限度地利用系統可用的並行而不超載

以下的答案可能是值得一試:

Parallel Task Library WaitAny Design

0

我想你會發現,庫只粗略地開始基於數量並行任務你有可用的核心。即對於I/O綁定的任務來說,這不是一個好的選擇,在這種情況下,您可能實際上要使用比CPU多的線程。

你不是說嵌套任務不啓動,是嗎?你只是說他們不會在你想要的時候開始,但會在晚些時候開始。

+0

是的,他們稍後開始,但我希望他們開始並行執行任務。如果我將循環中「i」索引的限制更改爲10,例如,我將創建並運行10個線程。但是沒有一個嵌套任務將與這些任務並行運行。 – lostaman 2010-07-28 13:01:54

+0

爲父任務添加TaskCreationOptions.LongRunning解決了問題。 – lostaman 2010-07-28 13:23:58

+0

它解決了下面的例子中的問題,但不是在我的項目:( – lostaman 2010-07-28 13:32:11