0

我在玩TPL,发现了一些很奇怪的东西。代码等待任务结束,做这个虚拟测试,发现Wait调用后执行了几个任务。我错过了什么,或者这是一个 TPL 问题?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Task tareas = null;

            Console.WriteLine("Start process");
            for (int i = 0; i < 4000; i++)
            {
                var n = i.ToString();
                tareas = Task.Factory.StartNew(() =>
                {
                    var random = new Random();
                    Thread.Sleep(random.Next(200, 500));

                    Console.WriteLine("Task completed: " + n);
                });
            }

            tareas.Wait();

            Console.WriteLine("Process end");

            Console.Read();
        }
    }
}

输出:

Start process
Task completed: 4
Task completed: 3

...

End process
Task completed: 3996
Task completed: 3991
Task completed: 3993
4

3 回答 3

2

好吧,tareas.Wait();只等待您创建的最后一个任务完成。由于您的任务在随机时间内完成,因此一旦您创建的最后一个任务完成,某些任务尚未完成是完全正常的。

以下是可能发生的情况的示例:

Task 1 created
Task 2 created
Task 3 created
Task 4 created

Task 1 completed
Task 3 completed

Wait for task 4 completion
Task 4 completed

// task 2 executed during more time than other 
// tasks because of the random value the thread waited
Task 2 completed
于 2013-03-28T17:36:59.933 回答
1

正如其他人所指出的,您只等待一个任务,即最后一个计划的任务。

默认情况下安排的任务使用线程池来执行此处TaskScheduler描述的工作项。使用此调度程序,无法保证排序。框架将尝试平衡池中每个线程上运行的队列,但有可能(并且并不罕见)放置最后一个计划任务的队列将在其他队列之前完成其所有任务的运行。

这甚至不考虑Wait. 查看我链接的文档中标记为“任务内联”的部分——如果正在等待任务,执行等待的线程可以说‘好吧,在这个任务完成之前我什么都做不了,让我看看我是否可以自己去执行”。在这种情况下,任务会完全从线程池队列中删除。

于 2013-03-28T17:41:06.193 回答
0

taereas 将包含对您最后创建的线程的引用,因此 treas.Wait() 将仅等待最后一个线程完成,因此即使在您的最后一个线程完成后其他线程也可能运行。

于 2013-03-28T17:39:23.267 回答