C# ParameterizedThreadStart是否保证对象实例赢了';垃圾不能收集吗?

C# ParameterizedThreadStart是否保证对象实例赢了';垃圾不能收集吗?,c#,delegates,lambda,thread-safety,C#,Delegates,Lambda,Thread Safety,我一直在使用以下代码: 类RunMeBaby { 公开作废开始() { while(true) { WriteLine(“我是”+Thread.CurrentThread.ManagedThreadId); 睡眠(1000); } } } 班级计划 { 静态void Main(字符串[]参数) { RunMeBaby r=新的RunMeBaby(); 线程t=新线程(r.Start);//参数化线程启动委托 r=null; GC.Collect(GC.MaxGeneration); t、 Sta

我一直在使用以下代码:

类RunMeBaby
{
公开作废开始()
{
while(true)
{
WriteLine(“我是”+Thread.CurrentThread.ManagedThreadId);
睡眠(1000);
}
}
}
班级计划
{
静态void Main(字符串[]参数)
{
RunMeBaby r=新的RunMeBaby();
线程t=新线程(r.Start);//参数化线程启动委托
r=null;
GC.Collect(GC.MaxGeneration);
t、 Start();
r=新RunMeBaby();
t=新线程(()=>r.Start());//线程启动委托
t、 Start();
//睡眠(1000);
r=null;
}
}
当main的第一部分顺利执行时,当我对
Thread.Sleep()
方法的调用进行注释时,第二部分失败,我得到一个null异常

我的理解是,lambda表达式被延迟计算时,可能会出现新线程启动不够快的情况,而主线程会先将
r
设置为
null
。现在,我把这个“第二部分”放在一个静态方法中,
r
有一个局部范围,问题就消失了。但我想知道,在这种特殊情况下,线程调度程序是否隐藏了问题,可能在具有不同工作负载的不同机器上,它仍然可能发生。或者lambda表达式中是否有某种东西可以保证,即使
r
不在范围内,只要它没有被设置为
null
,它仍然会以某种方式被引用


最后,我想知道我是否应该尽可能多地考虑使用<代码>参数化THEADSTART 委托,还是坚持给定的LAMBDAS,我尊重某些条件来保持它们的有效性。

< P>许多我都不懂的问题。我能说的是

Thread t = new Thread(r.Start)
创建一个委托,该委托将在内部指向提供通过委托调用的方法实现的实例。因此,将r设置为null不会有任何效果,因为存在一个关系:Thread->parametereddelegate->your method->RunMeBaby


围绕r创建一个闭包,它仍然允许您修改r。如果您将其设置为null并在稍后访问它,您将获得您的NRE

在我们讨论垃圾收集之前,首先让我们了解您编写的代码

这两者之间有着巨大的区别:

new Thread(r.Start)
它根据
r
的当前值为
Start
方法创建一个委托,即

new Thread(new ThreadStart(r.Start)) // identical to new Thread(r.Start)
在上述任何一种情况下,
r
现在进行计算,因此以后对另一个实例(或null)的更改不会影响它。与之相比:

new Thread(() => r.Start())
这是一个匿名方法,它使用捕获变量
r
,即
r
仅在调用匿名方法时,即在第二个线程运行时,才计算。因此,是:如果更改
r
的值,很可能会得到不同的结果(如果将其更改为null,则会出现错误)

参数化线程启动也会起作用:

new Thread(state => ((RunMeBaby)state).Start(), r);
它将
r
当前值作为参数值传递,因此现在是固定值;调用委托时,
state
获取当时在
r
中的值,因此您可以将该值转换为适当的类型并安全地使用它

现在!关于垃圾收集,没有什么特别需要知道的。是的,将引用
r
传递到
ParameterizedThreadStart
将创建引用的副本(不是对象的副本),因此将防止垃圾收集,直到它不再在范围内。然而,原始的
新线程(r.Start)
方法也是如此。唯一棘手的是“捕获变量”示例(
()=>r.Start()
),尽管您看到的问题与GC无关,与捕获变量的规则有关

new Thread(state => ((RunMeBaby)state).Start(), r);