C# GC.KeepAlive与using
Michael Covington在其应用程序示例中介绍了以下代码:C# GC.KeepAlive与using,c#,garbage-collection,keep-alive,C#,Garbage Collection,Keep Alive,Michael Covington在其应用程序示例中介绍了以下代码: static void Main() // args are OK here, of course { bool ok; m = new System.Threading.Mutex(true, "YourNameHere", out ok); if (! ok) { MessageBox.Show("Another instance is a
static void Main() // args are OK here, of course
{
bool ok;
m = new System.Threading.Mutex(true, "YourNameHere", out ok);
if (! ok)
{
MessageBox.Show("Another instance is already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
GC.KeepAlive(m); // important!
}
他解释说,需要GC.KeepAlive(m)来防止垃圾收集器提前收集互斥锁,因为没有对互斥锁的额外引用
我的问题是:将互斥体包装在using中会做同样的事情吗?也就是说,以下内容是否也会阻止GC从我下面拉出地毯
static void Main() // args are OK here, of course
{
bool ok;
using (var m = new System.Threading.Mutex(true, "YourNameHere", out ok))
{
if (! ok)
{
MessageBox.Show("Another instance is already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
}
}
我的直觉反应是使用会起作用,因为使用(应该)等同于:
Mutex m = new System.Threading.Mutex(true, "YourNameHere", out ok);
try
{
// do stuff here
}
finally
{
m.Close();
}
我认为m.Close()足以向JIT编译器发出信号,表明存在另一个引用,从而防止过早的垃圾收集。使用语句将互斥体包装在
中确实会防止它被垃圾收集,但也会处理它(它在最后调用Dispose
,而不是Close
)(而GC.KeepAlive
显然不会)
如果方法的结束真的是过程的结束,我不相信你所使用的方法可能会有任何实际的区别-我更喜欢使用语句,其基本原则是处理实现IDisposable
的任何东西
如果进程退出时没有释放互斥锁,我怀疑它的终结器会处理它——只要其他终结器不占用超过超时的终结线程
如果终结器不处理它,我不知道Windows本身是否会注意到进程不可能再拥有互斥锁,因为它(进程)不再存在。我怀疑它会存在,但您必须查看详细的Win32文档才能确定。使用使用似乎比使用GC.KeepAlive
更适合这种情况。您不仅希望在应用程序运行时保持互斥体的活动状态,还希望它也能保持活动状态在退出主循环时打开
如果您只是挂起互斥体而不处理它,那么它可能需要一段时间才能最终完成,这取决于应用程序关闭时需要做多少清理工作。我认为将KeepAlive与命名互斥体一起使用的原因是确保它不会提前被垃圾收集。C#使用/Dispose pattern不适用于这种情况。当对象引用不再在作用域内使用时,运行时可能会在作用域结束之前收集它。这是一种优化。我不是CLR专家(这就是为什么我不添加答案),但在我看来,你所做的应该是可行的。我说试试看。当谈论GC时,“试一试看”原来是个坏主意。我曾经有过这样的案例,测试说它应该可以工作,但在生产中失败了。这与JIT编译器在发行版和调试模式下的工作方式不同有很大关系。你是对的,它调用Dispose而不是Close,尽管在本例中结果是相同的(Close调用Dispose)。SDK文档说互斥将在程序退出时释放。与您一样,我也喜欢使用互斥。我刚才看到了这个问题,因为对Application.Run(new Form1())的调用在进程关闭之前不会返回,所以调用GC.KeepAlive(m)实际上,这并不重要,对吗?“是的。”——因为没有调用,对象可以被垃圾收集。“reference.@JonSkeet-如果您将互斥量设置为这个主方法所在的任何类的静态变量,并且这就是您所要做的一切(noDispose
,noKeepAlive
),这就足够让互斥锁继续存在吗?@Smashery:是的,我想是的。但这对我来说并不是一个干净的解决方案。你能提供证据支持这一说法吗?或者是一个测试用例,或者是文档?谢谢!