为什么任务没有执行

本文关键字:执行 任务 为什么 | 更新日期: 2023-09-27 18:37:27

我有以下代码:

class Program
{
    static void Main(string[] args)
    {
        Task[] tasks = new Task[3]
                        {
                            Task.Factory.StartNew(() => Console.WriteLine("Hello A")),
                            Task.Factory.StartNew(() => Console.WriteLine("Hello B")),
                            Task.Factory.StartNew(() => Console.WriteLine("Hello C"))
                        };
        Task.WaitAll(tasks); 
        Console.WriteLine("Hi ABC");
    }
}

我构建并运行上面的代码,它给出了输出:
你好 C
你好 B
你好 A
嗨,美国广播公司

但是如果我评论Task.WaitAll(tasks),其中一个输出是:
嗨,美国广播公司
你好 B
你好 C

这是否意味着当Console.WriteLine("Hi ABC")完成执行

时,执行Console.WriteLine("Hello A")的线程没有机会完成执行?

为什么任务没有执行

是的,没错。 主线程在子线程完成之前终止进程 - 或者在某些情况下启动。如果你不做一些事情来保持主线程忙碌,那么当主线程终止时(在"Hi ABC"之后),进程终止将杀死所有未完成的线程。如果尚未调度 A 线程(或任何子线程),则它根本没有机会输出。

如果不等待任务,则所有四个线程(三个任务加上主线程)将同时运行。

由于主线程不需要启动,因此可能会首先进入 print 语句。

这意味着线程结束或在程序完成后被杀死。您应该添加 Console.ReadLine();手动等待,您将看到它们都结束了。

如果没有WaitAll,执行将继续正常。在最后一次Console.WriteLine之后,应用程序将终止,因为它已到达程序末尾。

您在这里拥有的是所谓的"竞争条件"。 换句话说,Hello AHello BHello CHi ABC的顺序是任意的,并且可能会根据哪个线程首先完成而改变。 因此,不同的运行可能会产生不同的结果。

正在发生的事情是,您正在剥离这些线程,然后继续执行程序。 在这种情况下,争用条件是哪些线程可以在主执行线程死亡(程序结束)时被终止之前打印其输出。 主线程的输出不能保证是第一个,但由于它启动的开销较少,所以它很可能是第一个。 您可以通过将Task.WaitAll更改为System.Threading.Thread.Sleep(200)来测试这一点,并查看在修改传入 Sleep 方法的毫秒数时输出的内容。

无需等待,主线程就会终止子线程,无论它们处于何种状态。 在您提到的案例中,线程 B 和 C 在程序Console.WriteLine('Hi ABC')和结束之间完成。 线程 A 没有完成,因此它在输出之前就被杀死了。