C# GC.KeepAlive与using

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

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)来防止垃圾收集器提前收集互斥锁,因为没有对互斥锁的额外引用

我的问题是:将互斥体包装在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-如果您将互斥量设置为这个主方法所在的任何类的静态变量,并且这就是您所要做的一切(no
Dispose
,no
KeepAlive
),这就足够让互斥锁继续存在吗?@Smashery:是的,我想是的。但这对我来说并不是一个干净的解决方案。你能提供证据支持这一说法吗?或者是一个测试用例,或者是文档?谢谢!