.net 4.0 任务并行库。嵌套任务不启动

.net 4.0 任务并行库。嵌套任务不启动,.net-4.0,task,task-parallel-library,.net 4.0,Task,Task Parallel Library,我正在使用.NET新的TPL库,面对一些我无法解释的奇怪行为。在我的例子中,由于某些原因,嵌套任务没有启动。我已将解决方案简化为以下内容: bool flag = false; for (int i = 0; i < 5; i++) { Task.Factory.StartNew(() => { while

我正在使用.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);
bool标志=false;
对于(int i=0;i<5;i++)
{
Task.Factory.StartNew(()=>
{
while(true)//很多新任务
{
线程。睡眠(200);//做一些工作
Task.Factory.StartNew(()=>
{
flag=true;
});
}
});
}
《睡眠》(2000年);
Assert.IsTrue(标志);
我有5个同时运行的任务。每个任务从挂起队列中检索一些元素,执行一些操作,然后尝试运行嵌套任务以获取此操作的结果。问题是,如果元素太多(而(true)模拟了这一点),并且所有5个任务都在持续运行,那么嵌套任务不会启动。只有在大多数带有while循环的任务完成执行后,才能启动


while语句阻止嵌套任务运行似乎有问题,但我不知道是什么:)

我想您会发现,库只大致根据可用的内核数启动并行任务。i、 对于i/O受限的任务来说,这不是一个好的选择,因为实际上,您可能需要使用比CPU多得多的线程


你不是说嵌套任务不会启动,是吗?您只是说,它们不会在您希望的时间点开始,而是在以后开始。

我想您会发现,库只会大致根据可用的内核数启动并行任务。i、 对于i/O受限的任务来说,这不是一个好的选择,因为实际上,您可能需要使用比CPU多得多的线程


你不是说嵌套任务不会启动,是吗?您只是说他们不会在您希望的时间点开始,而是以后再开始。

您应该在此处阅读有关任务调度的部分:

PDF格式第63页及以后

LongRunning选项通过完全绕过线程池来“修复”您的问题。这有一些缺点,因为它将允许您创建比系统实际使用的线程更多的线程,这将导致过度的上下文切换,从而降低性能

像上面使用线程睡眠的代码这样的实验具有误导性,因为它们“愚弄”了调度程序。它看到它增加了更多的工作,但CPU负载没有增加。63您应该用一个包含数学的紧密循环(例如计算Sqrt()来代替睡眠

为什么不简单地使用一个外部循环从队列中读取项目并在任务中执行它们呢?这样应用程序就可以最大限度地利用系统的可用并行性,而不会使系统过载

下面的答案可能值得一看:


Task.Factory.StartNew不会启动任务,它会将任务添加到要调度的任务列表中,调度器会根据可用内核数(线程池大小)、当前CPU负载和现有工作的吞吐量等因素决定何时运行任务

您应该在此处阅读有关任务调度的部分:

PDF格式第63页及以后

LongRunning选项通过完全绕过线程池来“修复”您的问题。这有一些缺点,因为它将允许您创建比系统实际使用的线程更多的线程,这将导致过度的上下文切换,从而降低性能

像上面使用线程睡眠的代码这样的实验是误导性的,因为它们“愚弄”了调度程序。它看到它增加了更多的工作,但CPU负载没有增加。63您应该用包含数学的紧循环(例如计算Sqrt())来代替睡眠

为什么不简单地使用一个外部循环从队列中读取项目并在任务中执行它们呢?这样应用程序就可以最大限度地利用系统的可用并行性,而不会使系统过载

下面的答案可能值得一看:


是的。它们稍后启动,但我希望它们与执行任务并行启动。例如,如果我将循环中“I”索引的限制更改为10,我将创建并运行10个线程。但没有一个嵌套任务将与这些任务并行运行。添加TaskCreationOptions.LongRunning以执行父任务解决了问题。它在中解决了问题下面的示例不在我的项目中:(是的。它们稍后启动,但我希望它们与执行任务并行启动。例如,如果我将循环中“I”索引的限制更改为10,我将创建并运行10个线程。但是没有一个嵌套任务将与这些任务并行运行。为父任务添加TaskCreationOptions.LongRunning解决了问题。它解决了e中的问题以下示例,但不在我的项目中:(