我想知道为什么线程启动顺序与执行顺序不一致。
这是我的代码。
class Test
{
public Test()
{
Thread t1 = new Thread(new ThreadStart(Run));
Thread.CurrentThread.Name = "Primary Thread";
t1.Name = "Secondary Thread";
t1.Start();
Run();
}
void Run()
{
Debug.WriteLine($"Thread#{Thread.CurrentThread.Name}: Begin");
Thread.Sleep(5000);
Debug.WriteLine($"Thread#{Thread.CurrentThread.Name}: End");
}
}
t1
线程在代码中早于Main Thread
开始。但是,Main Thread
首先执行。
为什么会这样?
谢谢。
答案 0 :(得分:6)
在编写更多多线程代码之前,您需要学习多线程编码的基本规则。
在单线程代码中,您可以假定所有内容保持不变,除非某些原因导致更改。在多线程代码中,您必须假定事物在不断变化,除非某些事物保持不变。
您的示例是该一般规则的一个特定案例。在这种情况下,不断变化的“东西”是观察到副作用的顺序。您几乎没有做任何事情来保持该“内容”不变,因此它可能会任意更改。
C#在C#规范中记录了非常具体,明确的规则,涉及在多线程程序中必须注意哪些副作用必须以特定的顺序出现。这是一个非常短的列表,并且程序中的副作用不在该列表中。
允许两个线程以彼此之间的任何顺序运行它们的副作用 ,但实际上这更糟。在C#中,不需要多个线程来提供从每个线程观察到的副作用的一致顺序。
实际上,在您的示例中,您观察到已选择了对Debug.Write的特定调用顺序。正在运行的程序可以选择任何交错这些副作用的顺序;您可以保证的是,在同一线程上的Begin
之后,在一个线程上 您不会看到End
。
您的问题是:
为什么会这样?
但是正如我们所看到的,这是一个错误的问题。观察到的行为允许发生,并且发生发生,因此询问为什么发生不会帮助您。 我想您要提出的问题是:
如何强制两个线程相对于彼此以特定顺序运行其副作用?
但是这也不是正确的问题。正确的问题是:
如何使用异步方式安全有效地解决特定的性能问题?
该问题的答案取决于实际问题,并且创建线程通常不是正确的解决方案。 理想情况下,仅当您有要解决的CPU绑定任务以及该线程可以接管的空闲CPU时,才创建线程。通常,最好使用await
在单个线程上解决涉及异步的性能问题。
答案 1 :(得分:1)
如果使用简单的英语措词,此结果将更有意义:
My To-Do List:
Instruct Bob to go off and do something
Begin doing something yourself
...,您得到的结果是鲍勃在开始工作之前就已经开始工作。所以?没有理由认为Bob会比您开始时快/慢。鲍勃只是打你一拳。
与您的代码相同。您告诉一个单独的任务开始,然后启动了一个功能。两位代码分别做着两件事–确实没有任何理由怀疑一个代码的启动速度要比另一个代码快。