C#线程启动顺序不一致

时间:2018-08-28 15:26:04

标签: c# multithreading

我想知道为什么线程启动顺序与执行顺序不一致。

这是我的代码。

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首先执行。 为什么会这样?

谢谢。

2 个答案:

答案 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会比您开始时快/慢。鲍勃只是打你一拳。

与您的代码相同。您告诉一个单独的任务开始,然后启动了一个功能。两位代码分别做着两件事–确实没有任何理由怀疑一个代码的启动速度要比另一个代码快。