运行 几个简单的任务似乎不能一起工作

Run a few simple tasks at once seems to not work together

我遇到了一个问题,如果我们查看控制台写入顺序,每个任务的输出并不像它应该的那样真实。

using System;
using System.Threading.Tasks;

namespace randomTaskTest
{
    class Program
    {
        public static void foo()
        {
            Random rnd = new Random((int)DateTime.Now.Ticks); // I know that I should not cast long to int

            int target = 3;
            int currentNumber = rnd.Next(1, 100);
            int tryCounter = 0;

            while(currentNumber!=target)
            {
                currentNumber = rnd.Next(1, 100);
                tryCounter++;
            }

            Console.WriteLine(tryCounter);
            rnd = null;
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 30; i++)
                Task.Run(() => { foo(); });

            Console.ReadKey();
        }
    }
}

我在其中放置了 30 个循环任务,直到随机 class 将在 <1;100> 范围内找到正确的数字。在完美世界中,控制台 window 中的第一个输出条目应该按升序 排序,但事实并非如此。

我对这段代码的理解是,当找到一个随机数时,应该尽快将其写入控制台window,因为最幸运的随机实例最先离开循环。

输出类似于: 3
18
7
30

而不是
3
7
18
30

等等

当Task创建时间长于Task执行时间时,这是无法避免的,是吗?至少我认为这个任务结束的时间比创建它的任务时间要少。

任务 API 正在后台使用线程池(或其他线程)。具体执行哪个线程以及执行多长时间取决于操作系统如何在后台调度线程。

例如:假设您有两个核心,而您 运行 只有两个任务。两个任务都在执行中,都在 5 次试验中。现在后台的一些系统进程需要做一些计算,因此操作系统不得不暂停两个并行任务中的一个 运行。其他任务现在继续,比方说,500 次试验并在需要时间的系统进程再次为其他任务扫清道路之前将它们打印出来,然后立即击中目标并打印出 6。

这被称为竞争条件,你不应该依赖于某些东西比其他东西更早完成,因为 OS 在后台做了很多事情,你永远无法说出哪个 thread/task 将在确切的时间执行。这是一个难以发现的常见错误来源。 :-)

此外,您的处理器只能同时执行与它拥有的内核一样多的任务。当发出的任务多于可用内核时,API 要么等待其中一些任务完成,要么暂停一些任务,稍后再恢复。这也导致每个任务的处理器时间不规则。