我有一个简单的.NET程序,它会检查另一个实例是否已经启动:
Mutex mutex = new Mutex(false,"MyMutexName");
if (!mutex.WaitOne(1))
return;
try{
//do stuff
}
catch{ //exceptions}
finally
{
mutex.ReleaseMutex();
}
我的问题是,如果你忘记在程序结束时释放它,那么互斥锁究竟会发生什么?在某些Windows控制面板组件中是否可见?它住在哪里?
答案 0 :(得分:12)
它是一个命名的互斥锁,因此它是可见的,可以在其他进程中打开。 Windows在句柄上使用简单的引用计数。如果您没有自己Dispose()它,那么终结器将为您关闭句柄。如果你的程序很难轰炸并且永远不会执行终结器,那么Windows会在清理程序使用的资源时执行此操作。
这将自动减少引用计数。如果减少到零(没有其他进程打开句柄),则释放内核对象。
换句话说:无论事情多么糟糕,你都没有问题。实际的突变对象存在于内核内存池中。您可以使用SysInternals的WinObj工具查看它。
答案 1 :(得分:3)
互斥锁是操作系统级别的句柄。当你的过程发生时它们会被关闭(如果你没有尽快关闭它们,那就是。)
修改的
好的,我明显误解了示例和这个问题。如果您只是想检测是否存在另一个实例,那么您将创建一个命名的互斥锁(或类似的对象),只需检查其存在而不锁定它。
对WaitOne
的调用锁定了它,取得了所有权,而ReleaseMutex
则取消了它(只要没有对WaitOne
的额外调用)。如果在没有完全释放互斥锁的情况下结束线程,它会使对象处于错误状态,如Micah引用文中所述。
我提出的问题是关于在流程完成之前是否关闭句柄,这完全是另一回事。
附加
在SDK [API] [1]级别,当已经创建了相同名称的互斥锁时,您可以调用CreateMutex
并期望失败。在.NET中(至少在4.0中),有一个[constructor] [2]填充createdNew
bool。
[1]:http://msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx CreateMutex
[2]:http://msdn.microsoft.com/en-us/library/bwe34f1k(v=VS.90).aspx Mutex
答案 2 :(得分:3)
来自MSDN
如果线程在拥有a时终止 mutex,据说是互斥体 弃。互斥体的状态是 设置为发信号,然后等待 线程获得所有权。如果没有人拥有 互斥体,互斥体的状态是 信号。从版本2.0开始 .NET Framework,一个 抛出AbandonedMutexException 获取的下一个线程 互斥。在版本2.0之前 .NET Framework,也不例外 抛出。
<强>注意强>
一个废弃的互斥体通常表示一个 代码中出现严重错误。当一个 线程退出而不释放 互斥,数据结构受到保护 由互斥体可能不在 一致的状态。下一个线程 请求互斥锁的所有权 处理此异常并继续,如果 数据结构的完整性 可以验证。
在系统范围的互斥锁的情况下, 废弃的互斥体可能表明一个 申请已被终止 突然(例如,通过使用 Windows任务管理器)。