我有以下代码,我使用Thread
对象作为构造函数参数启动ParameterizedThreadStart
:
static object obj = new object();
static void Main(string[] args)
{
ParameterizedThreadStart start = (o) =>
{
ThreadTest(o);
};
var t = new Thread(() => start(obj));
t.Name = "t";
t.Start();
Thread.Sleep(3000);
obj = null;
// Why the Thread (t) continue here??
Console.ReadKey();
}
private static void ThreadTest(object o)
{
while (o != null)
{
Console.WriteLine(Thread.CurrentThread.Name);
Thread.Sleep(1000);
}
}
我在obj
方法中将null
设置为ThreadTest
后,参数o
仍然是有效对象,为什么?
如何使用o
将参数null
设置为obj
?
答案 0 :(得分:7)
因为在C#中,引用是按值传递的。
因此,在Main中更改obj以引用NULL将不会更改在ThreadTest中引用的对象。
相反,您应该保持两个方法引用同一个对象,并且只是更改对象的属性以表示线程应该退出。
答案 1 :(得分:5)
o
是ThreadTest
方法中的本地参数
分配obj
字段不会影响该参数。
您可以通过删除所有参数并直接使用该字段来解决此问题。一旦你这样做,你的代码仍然会被破坏,因为该字段不易变。
答案 2 :(得分:3)
调用方法时,您传递了引用的值。这意味着对内部参考的任何更改都不会在外部看到,反之亦然。您可能希望直接在全局变量级别进行同步:
static volatile object obj = new object();
static void Main(string[] args)
{
ThreadStart start = () =>
{
ThreadTest();
};
var t = new Thread(() => start());
t.Name = "t";
t.Start();
Thread.Sleep(3000);
obj = null;
// Why the Thread (t) continue here??
Console.ReadKey();
}
private static void ThreadTest()
{
while (obj != null)
{
Console.WriteLine(Thread.CurrentThread.Name);
Thread.Sleep(1000);
}
}
还请注意对象上的volatile
。这将确保读取该值的其他线程可以看到一个线程的更改。
答案 3 :(得分:0)
尝试使用布尔值来控制线程停止,如下所示:
static volatile bool runThread = true;
static void Main(string[] args)
{
var t = new Thread(ThreadTest);
t.Start();
Thread.Sleep(3000);
runThread = false;
Console.ReadKey();
}
private static void ThreadTest()
{
while (runThread)
{
Console.WriteLine(Thread.CurrentThread.Name);
Thread.Sleep(1000);
}
}