2014-09-06 167 views
-1

我需要你的幫助。我只是開始學習線程主題。 爲什麼打印't2'兩次?C#線程共享數據

 string text = "t1"; 
     Thread t1 = new Thread (() => Console.WriteLine (text)); 
     t1.Start(); // why do not print 't1'? 
     text = "t2"; 
     Thread t2 = new Thread (() => Console.WriteLine (text)); 
     t2.Start(); // print 't2' 

輸出:

t2 
t2 
+1

運行足夠多的時間,它實際上可能會偶爾 – 2014-09-06 06:29:09

+2

而不是downvoting他的問題,只是向他提供一些建議。 – RajeshKannan 2014-09-06 06:33:10

回答

5

因爲共享text。線程t1可以在線程t1可以打印任何東西之前開始(在後臺)並且文本可以被分配給t2。所以兩者都打印t2。如果事情發生得足夠快,它可能會偶爾打印t1,然後是t2。

因爲一個簡單的例子給出我會給出一個簡單的解決方案(雖然不是太有用):

string text = "t1"; 
Thread t1 = new Thread(() => Console.WriteLine(text)); 
t1.Start(); // why do not print 't1'? 
t1.Join(); // Wait for thread t1 to finish before continuing 

text = "t2"; 
Thread t2 = new Thread(() => Console.WriteLine(text)); 
t2.Start(); // print 't2' 

所不同的是,你等待的線程T1完成分配text新值之前執行。我只給這個例子說明如何使用Join來等待一個線程完成。

稍微複雜一點的方法是不使用Lamda表達式。如果您創建一個靜態函數來完成工作,你可以通過一個單一的參數(任何類型的object)的線程啓動功能:

public static void DoPrint(object data) 
    { 
     Console.WriteLine((String)data); 
    } 

    static void Main(string[] args) 
    { 
     string text = "t1"; 
     Thread t1 = new Thread(DoPrint); 
     t1.Start(String.Copy(text)); // Pass a copy of text to Thread and start 

     text = "t2" 
     Thread t2 = new Thread(DoPrint); 
     t2.Start(String.Copy(text)); // Pass a copy of text to Thread and start 
    } 

注意我們是如何使文本數據的副本傳遞之前。即使text = "t2"在線程t1打印之前完成,它也不會影響,因爲副本已通過。有兩個開始線:

 t1.Start(text); 
     t2.Start(text); 

然後,我們將有同樣的問題作爲原來的例子出於同樣的原因。文本是一個字符串,字符串是一個Class,因此它們通過引用傳遞。

+0

謝謝。作品。 或添加:'Thread.Sleep(10);' – GUImaniac94 2014-09-06 06:56:41

+1

@ GUImaniac94做睡眠不會「解決」問題,它只是使它不太可能發生。如果你需要一個特定的事件發生順序,你必須在那裏停止一些停止,直到你正在等待的東西完成(這是'.Join()'的作用)。比較兩種方式,你的方法:'設置值,開始顯示,希望它在下一個10ms內完成顯示,設置值,開始顯示'Michaels方式:'設置值,開始顯示,等待它完成顯示,設置價值,開始顯示' – 2014-09-06 07:03:26

0

因爲T1開始工作之前,文本變量分配給 「T2」,然後2和T1開始同時工作。