为什么任务没有执行
本文关键字:执行 任务 为什么 | 更新日期: 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("Hello A")的线程没有机会完成执行?
是的,没错。 主线程在子线程完成之前终止进程 - 或者在某些情况下启动。如果你不做一些事情来保持主线程忙碌,那么当主线程终止时(在"Hi ABC"之后),进程终止将杀死所有未完成的线程。如果尚未调度 A 线程(或任何子线程),则它根本没有机会输出。
如果不等待任务,则所有四个线程(三个任务加上主线程)将同时运行。
由于主线程不需要启动,因此可能会首先进入 print 语句。
这意味着线程结束或在程序完成后被杀死。您应该添加 Console.ReadLine();手动等待,您将看到它们都结束了。
如果没有WaitAll
,执行将继续正常。在最后一次Console.WriteLine
之后,应用程序将终止,因为它已到达程序末尾。
您在这里拥有的是所谓的"竞争条件"。 换句话说,Hello A
、Hello B
、Hello C
和Hi ABC
的顺序是任意的,并且可能会根据哪个线程首先完成而改变。 因此,不同的运行可能会产生不同的结果。
正在发生的事情是,您正在剥离这些线程,然后继续执行程序。 在这种情况下,争用条件是哪些线程可以在主执行线程死亡(程序结束)时被终止之前打印其输出。 主线程的输出不能保证是第一个,但由于它启动的开销较少,所以它很可能是第一个。 您可以通过将Task.WaitAll
更改为System.Threading.Thread.Sleep(200)
来测试这一点,并查看在修改传入 Sleep
方法的毫秒数时输出的内容。
无需等待,主线程就会终止子线程,无论它们处于何种状态。 在您提到的案例中,线程 B 和 C 在程序Console.WriteLine('Hi ABC')
和结束之间完成。 线程 A 没有完成,因此它在输出之前就被杀死了。