Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解多线程C#_C#_Multithreading - Fatal编程技术网

理解多线程C#

理解多线程C#,c#,multithreading,C#,Multithreading,我试图理解多线程。我有一个例子,从控制台应用程序的Main方法运行两个线程 new Thread(() => { for (int x = 0; x < 10; x++) { Console.WriteLine("First :" + x); } }).Start(); new Thread(() => { for (int x = 0; x < 10; x++) { Console.WriteL

我试图理解多线程。我有一个例子,从控制台应用程序的Main方法运行两个线程

new Thread(() =>
{
    for (int x = 0; x < 10; x++)
    {
        Console.WriteLine("First :" + x); 
    }
}).Start();

new Thread(() =>
{
    for (int x = 0; x < 10; x++)
    {
        Console.WriteLine("Second :" + x);
    }
}).Start();

Console.ReadKey();
新线程(()=>
{
对于(int x=0;x<10;x++)
{
控制台写入线(“第一条:+x”);
}
}).Start();
新线程(()=>
{
对于(int x=0;x<10;x++)
{
控制台写入线(“第二条:+x”);
}
}).Start();
Console.ReadKey();
发生的事情是,我的控制台是黑色的,上面没有写任何东西,但当我按下任何键时,它会显示正确的结果。为什么?

我们中的一些人(查看问题下的注释)看到新线程在调用
Console.ReadKey()
之前全部执行,而其他人看到初始线程抢占新线程,在执行新线程之前等待通过
Console.ReadKey()
输入

您有三个线程,它们都在做自己的事情,都可能写入控制台并执行其他逻辑,而您实际上无法控制在任何特定时刻执行哪个线程

从上面所说的,这种行为是可以预料的,而您执行新线程的方式是不可预测的。(在这里转载他的评论,以防评论被清理干净)

再次阅读我的两条基本规则:(1)尝试在两个线程上执行UI的程序被破坏,(2)不希望任何东西正常运行。我不期望给出的坏程序会产生任何行为。此外,我不期望一个坏程序的行为在多个运行或多台机器上是一致的我也不希望行为不一致。坏掉的程序坏掉了;他们的不良行为不需要前后一致

有一个调用将允许您阻止初始(主)线程(恰好是调用线程),直到新线程完成执行,这就是。您仍然无法控制两个新线程执行和写入控制台的顺序,但至少初始线程已暂停

var threads = new Thread[] {
    new Thread(() =>
    {
        for (int x = 0; x < 10000; x++)
        {
            Console.WriteLine("First :" + x);
        }
    }),
    new Thread(() =>
    {
        for (int x = 0; x < 10000; x++)
        {
            Console.WriteLine("Second :" + x);
        }
    })
};

// start the threads
foreach (var t in threads)
    t.Start();

// block the initial thread until the new threads are finished
foreach (var t in threads)
    t.Join();

// Now the following line won't execute until both threads are done
Console.ReadKey();
var threads=新线程[]{
新线程(()=>
{
对于(int x=0;x<10000;x++)
{
控制台写入线(“第一条:+x”);
}
}),
新线程(()=>
{
对于(int x=0;x<10000;x++)
{
控制台写入线(“第二条:+x”);
}
})
};
//启动线程
foreach(线程中的变量t)
t、 Start();
//阻塞初始线程,直到新线程完成
foreach(线程中的变量t)
t、 Join();
//现在,在两个线程都完成之前,将不会执行下面的行
Console.ReadKey();

让我将第一个衍生线程称为thread1,将下一个衍生线程称为thread2。此外,让我们调用创建thread1和thread2作为主线程的线程

粗略地说,不能保证thread1中的代码在thread2或mainthread之前执行。因此,根据不同的情况,它可能会在停止执行
Console.ReadKey()
之前执行一些
Console.WriteLine()

您可能会问,为什么它会停在Console.ReadKey()上;因为控制台I/O是同步的。控制台周围有一个
lock
语句。*调用可能会使它更明显(对于演示代码)


如果希望其他两个线程在调用
Console.ReadKey()
(阻止I/O调用)之前完成处理,则应在调用
Console.ReadKey()

之前调用
thread1.Join()
thread2.Join()
,因为
Console
的操作是同步的
ReadKey()
IO
上放置一个块。您的实验应该教会您编写多线程编程的两个基本规则。首先,不要编写两个线程试图操纵用户界面的多线程程序。这样的程序几乎总是坏的和错误的。专用于与用户通信的单个线程;其他线程必须说服该线程执行该工作。第二,学会期待世界不再正常运转。在单线程编程中,语言内置了对事件发生顺序的保证。这些保证都消失了。@EricLippert你知道为什么
Console.ReadKey()
在某些情况下会阻止IO,而在其他情况下不会阻止它吗?@Rob:再次阅读我的两条基本规则:(1)尝试在两个线程上执行UI的程序被破坏了,以及(2)不希望任何东西正常运行。我不期望给出的坏程序会产生任何行为。此外,我不期望一个坏程序的行为在多个运行或多台机器上是一致的。我也不期望这种行为会前后不一致。坏的程序坏了;它们的不良行为不需要一致或不一致。@Imad:我的第二点意思是,当您开始编写多线程程序时,您认为程序应该做的事情不再适用。在单线程程序中,你可以说“这些变量将保持不变,直到有东西改变它们”。在多线程程序中,您必须始终推理“这些变量不断变化,直到有东西使它们保持静止”。这是一种根本不同的态度,这意味着你对“应该”发生什么的直觉可能与现实大相径庭。这个答案说明了一个关键点:当你生活在一个多线程的世界中,在这个世界中,一切都在移动,而不是被迫保持静止,关于以什么顺序发生的事情,只有少数几个保证。事实上,启动和连接线程确实为您提供了一些保证:逻辑上在启动之前发生的效果确实在启动之前发生,并且在可以观察到线程的工作完成之前,连接不会返回。现在:我刚才说的是一个夸张的说法