2013-05-07 132 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之前通話。它被稱爲「競賽條件」