GC.KeepAlive与使用

时间:2009-03-11 17:55:17

标签: c# garbage-collection keep-alive

在他的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编译器发出信号,告知还有另一个引用,从而防止过早的垃圾收集。

3 个答案:

答案 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模式不是为了保护它。当在范围内不再使用对象引用时,运行时可以在范围结束之前收集它。这是一个优化。