我需要你的帮助。我刚开始学习线程主题。 为什么两次打印't2'?
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
答案 0 :(得分: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'
区别在于您在为text
分配新值之前等待线程t1完成执行。我只举例说明如何使用Join来等待线程完成。
稍微复杂一点的方法是不使用Lamda表达式。如果你创建一个静态函数来完成工作,你可以将一个参数(任何类型的object
)传递给线程上的Start函数:
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
}
请注意我们如何在传入之前复制文本数据。这样即使{1}}在线程t1打印之前完成它也无关紧要,因为传递了副本。有两个开始行:
text = "t2"
然后,出于同样的原因,我们会遇到与原始示例相同的问题。 text是一个字符串,字符串是一个Class,因此它们通过引用传递。
答案 1 :(得分:0)
因为在t1开始工作之前,文本变量分配给“t2”,然后2和t1开始同时工作。