2013-05-07 53 views
4

我遇到了一些问题,我不明白为什么会发生。 下面是简单的例子:有时线程无法启动

class ConsoleApp 
{ 
    static void Main(string[] args) 
    { 
    Thread workThread = new Thread(ThreadProc); 
    //Console.WriteLine("Starting"); // uncomment this 
    workThread.Start(); 
    Console.ReadKey(true); // first ReadKey 
    Console.ReadKey(true); // second ReadKey 
    } 

    static void ThreadProc() 
    { 
    Console.WriteLine("ThreadProc started"); 
    Random rnd = new Random(); 
    for (int i = 0; i < 5; i++) 
    { 
     int timeout = rnd.Next(500, 1000); 
     Thread.Sleep(timeout); 
     Console.WriteLine("ThreadProc {0} slept {1} ms", i, timeout); 
    } 
    } 
} 

当我运行此,workThread没有启动,直到我按一些键(第一ReadKey后)。如果我取消注释第一个Console.WriteLine,workThread立即启动。

任何人都可以解释这种行为吗?

+9

竞赛条件。请参阅http://stackoverflow.com/questions/15143931/strange-behaviour-of-console-readkey-with-multithreading – Maarten 2013-05-07 07:30:28

+0

我复制了您的代码并尝试了该操作,但该线程立即启动,无论是评论还是取消注释该行。 – 2013-05-07 07:31:32

+0

我不能重复这一点。这是在什么环境下运行的? – Nick 2013-05-07 07:33:00

回答

4

这是一个理想的情况竞赛条件。在这里你正在创建一个线程,然后启动它。但请记住,一旦您调用start方法,线程就会延迟实际运行。可能这种延迟为您的Console.ReadKey方法带来了执行流程并等待用户输入的机会。在这个阶段,Console.ReadKey方法通过锁定Console.InternalSyncObject来阻止您的控制台,并阻止等待输入。这种情况下,其他执行路径将阻塞,直到我们键入。一旦您按下密钥,间接释放锁Console.InternalSyncObject,并允许线程继续执行。我认为,这是你的情况。

虽然不是要取代您试图实现的目标,但您可以在将Console.RedKey更换为Console.ReadLine()时看到执行的线程。

+2

线程立即启动。它是'Console.WriteLine',它在完成执行之前等待控制台锁释放。 – 2013-05-07 07:49:23

0

静态类Console是线程安全的,里面有一个锁。有时ReadKey通话会在您拨打ThreadProc之前通话。它被称为“竞赛条件”