2010-07-28 43 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