TPL等待好奇心

时间:2013-03-28 17:33:10

标签: c# multithreading task-parallel-library

我正在玩 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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

正如其他人所说,你只等待一个任务,最后一个任务。

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

这甚至没有考虑Wait。查看我链接的文档中标记为“任务内联”的部分 - 如果正在等待任务,执行等待的线程可以说'好吧,在完成此任务之前我无法做任何事情,让我看看是否我可以继续自己执行它。在这种情况下,任务将完全从线程池队列中删除。

答案 2 :(得分:0)

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