2014-09-06 170 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开始同时工作。