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 循环的任务完成执行后才能启动。

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

4

2 回答 2

3

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

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

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

PDF 的第 63 页起。

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

上面使用线程睡眠的代码之类的实验具有误导性,因为它们“欺骗”了调度程序。它发现它增加了更多的工作,但 CPU 负载并没有增加。63 您应该用包含数学的紧密循环替换睡眠(例如计算 Sqrt()。

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

以下答案可能值得一看:

并行任务库 WaitAny Design

于 2010-07-30T23:12:08.283 回答
0

我想您会发现该库仅根据您可用的内核数量大致启动并行任务。即,对于受 I/O 限制的任务来说,这不是一个好的选择,在这些任务中,您实际上可能希望使用比 CPU 多得多的线程。

你不是真的说嵌套任务没有启动,是吗?你只是说他们不是在你希望他们开始的时候开始,而是稍后开始。

于 2010-07-28T11:40:32.443 回答