C#互斥锁在发布模式下的行为与调试模式不同

6

以下是我的代码:

...
private static void Main(string[] args)
{
    string file=DateTime.Now.ToFileTime().ToString();
    File.AppendAllText(file, "Mutex\r\n");

    bool CreatedNew;
    Mutex mutex=new Mutex(true, AppDomain.CurrentDomain.FriendlyName, out CreatedNew);

    if(CreatedNew)
    {
        #if DEBUG
        File.AppendAllText(file, "Launching in DEBUG mode\r\n");
        #else
        File.AppendAllText(file, "Launching in RELEASE mode\r\n");
        #endif

        //Program.Launch();
        Program.ProcessArgsAndLaunch(args);
    }
    else
    {
        File.AppendAllText(file, "Handling dupe\r\n");
        Program.HandleDuplicate();
    }
}
...

我已经查看了许多文章,包括这里和其他网站,但都没有找到答案。
基本上,代码检查应用程序的运行实例,并在存在实例时切换到其主窗口。如果没有实例,则启动该应用程序。
在“Debug”模式下,一切都如预期般工作,问题出现在我将配置切换为“Release”时:应用程序总是启动(Mutex似乎什么也没做)。
我已经添加了有条件编译的转储,显示应用程序启动的模式,并且输出根据配置而改变,但不幸的是,应用程序的行为也是如此。
这可能是一个竞争条件,但我不确定。
如果需要,将发布更多代码。
谢谢。
2个回答

13
除了Juan的答案外,启动调试器内部和外部之间在垃圾回收方面存在差异。这不完全等同于Debug配置与Release配置之间的区别,但无论如何,您都应该意识到这一点。
在调试器中,局部变量将在其整个范围内充当GC根 - 但是当您不进行调试时,您的mutex变量根本不是GC根,因为您在初始化后没有使用它。这意味着您的Mutex可以立即被垃圾回收(因此本地mutex将被释放)。
您应该使用using语句在正确的时间显式释放Mutex:
// Note that you don't need a variable here... you can have one if you
// want though
using (new Mutex(...))
{
    // Code here to be executed while holding the mutex
}

1
非常感谢Jon,这就是问题所在。一旦我将代码放入“using”语句中,它就可以正常工作了。而且你是对的,我不需要那个变量... - nurchi

8
如果您有一个实例以Debug模式运行,另一个实例以Release模式运行,它们将不共享同一互斥锁,因为AppDomain.CurrentDomain.FriendlyName依赖于托管进程是否处于活动状态而有所不同。
如下文所示:http://msdn.microsoft.com/en-us/library/ms242202.aspx

抱歉如果之前表述不清楚。我会在“Debug”或“Release”下编译,然后从“资源管理器”中启动新编译的应用程序。然后我会关闭(所有)实例,清理解决方案,更改配置,重新编译,再次从“Windows资源管理器”中启动... - nurchi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接