ThreadPoolTask​​Scheduler内部-Task.WaitAll()的参数顺序是否会更改执行顺序?

时间:2018-10-17 14:19:55

标签: c# .net task task-parallel-library threadpool

我在工作中遇到过以下情况。 (出于这个线程的目的,我对此做了一些简化)

这是代码(.net核心控制台应用程序):

private void UseVars(List<string> vars) {
    foreach (string s in vars)
        DoSomethingWith(s);

    // OR
    for (int i = 0; i < vars.Count; i++)
        DoSomethingWith(vars[i]);
}

当我使用8次或更多次循环迭代运行此代码时,所有T2任务都未启动之前,没有T1任务启动,这似乎很奇怪。我的问题是为什么会这样?我本来希望任务以完全随机的顺序开始。

这是示例执行(8次迭代)输出的开始:

class Program
{
    static void Main(string[] args)
    {
        const int numberOfTasks = 15;
        var taskArray = new Task[numberOfTasks];

        for (int i = 0; i < numberOfTasks; i++)
        {
            var temp = i;
            taskArray[i] = Task.Run(() => SingleTest(temp));
        }

        Task.WaitAll(taskArray);
        Console.WriteLine("FINISHED!!!");

        Console.ReadKey();
    }

    static void SingleTest(int temp)
    {
        var signal = new AutoResetEvent(false);
        var t1 = Task.Run(() =>
        {
            Console.WriteLine($"{temp} T1 started");
            signal.Set();
            Console.WriteLine($"{temp} T1 finished");
        });

        var t2 = Task.Run(() =>
        {
            Console.WriteLine($"{temp} T2 started");
            signal.WaitOne();
            Console.WriteLine($"{temp} T2 finished");
        });

        Task.WaitAll(t1, t2);
        //Task.WaitAll(t2, t1);
        Console.WriteLine($"{temp}: Both tasks finished");
    }
}

当我更改Task.WaitAll()调用中参数的顺序时(如注释行中所示),其行为就大不相同了,其中任务以(看似)随机顺序启动(大多数T1任务)似乎早于其T2等效项开始,但是至少在完成所有T1任务之前启动了一些T2任务)

示例输出:

5 T2 started
7 T2 started
3 T2 started
0 T2 started
4 T2 started
6 T2 started
2 T2 started
1 T2 started
1 T1 started
1 T1 finished
1 T2 finished
1: Both tasks finished
...

那么,我想知道的是,在幕后为了创造这种行为正在发生什么?

0 个答案:

没有答案