在他的article about preventing multiple instances申请中,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 already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
GC.KeepAlive(m); // important!
}
他解释说GC.KeepAlive(m)是防止垃圾收集器尽早收集互斥锁所必需的,因为没有额外的引用。
我的问题:将mutex包装在一个使用中做同样的事情?也就是说,下面是否还会阻止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编译器发出信号,告知还有另一个引用,从而防止过早的垃圾收集。
答案 0 :(得分:17)
在using
语句中包装互斥锁确实会阻止它被垃圾回收,但是也会处理掉它(它调用Dispose
,而不是Close
})最后(而GC.KeepAlive
显然不会。)
如果方法的结尾真的是这个过程的结束,我不相信它可能会使你使用的任何实际差异 - 我更喜欢关于一般原则的using
陈述。处置任何实现IDisposable
。
如果在进程退出时没有处理互斥锁,我怀疑它的终结器会处理它 - 只要其他终结器不会超出终结线程超过其超时。
如果终结器没有处理它,我不知道Windows本身是否会注意到该进程不再可能拥有互斥锁,因为它(进程)不再存在。我怀疑它会,但你必须检查详细的Win32文档,以确定。
答案 1 :(得分:5)
在这种情况下,使用using
似乎比使用GC.KeepAlive
更合适。只要应用程序正在运行,您不仅希望保持Mutex
活着,还希望它在退出主循环后立即消失。
如果您只是暂停Mutex
而不进行处理,可能需要一段时间才能完成,具体取决于应用程序关闭时要进行的清理工作量。
答案 2 :(得分:-2)
我认为KeepAlive与命名的Mutex一起使用的原因是为了确保它不是早期的垃圾收集。 C#using / Dispose模式不是为了保护它。当在范围内不再使用对象引用时,运行时可以在范围结束之前收集它。这是一个优化。