我不确定是否已经很好地理解了如何处理互斥。我需要一个进程只运行一次,但如果由于任何原因它意外崩溃或关闭,我还需要重置被放弃的互斥锁。
出于这个原因,我做了一个助手调用,试图获取一个具有超时的互斥锁(由名称标识)。如果获取互斥锁失败,则返回NULL,否则返回将由方法调用者处理的互斥锁。如果互斥锁被放弃,我将重置它,并将请求视为失败(不是代码被插入以在周期性过程中使用的问题,如果锁有时失败,那么过程将恢复到下一次运行)。
我要问的是,是否有一些情况我没有考虑到,可能会导致我的问题
这里的代码:
public class MutexManager
{
/// <summary>
/// Try to acquire a global mutex
/// </summary>
/// <param name="mutexName">Mutex unique name</param>
/// <param name="timeout_ms">Timeout in milliseconds (Optional : default = 5000, if <= 0 no timeout is applied, infinite wait and possibile daeadlock) </param>
/// <returns>The acquired Mutex or null if Mutex can not be acquired</returns>
public static Mutex TryRegister(string mutexName, int timeout_ms = 5000)
{
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", mutexName);
bool createdNew;
var allowEveryoneRule =new MutexAccessRule( new SecurityIdentifier(WellKnownSidType.WorldSid
, null)
, MutexRights.FullControl
, AccessControlType.Allow
);
Mutex mutex = null;
{
mutex = new Mutex(false, mutexId, out createdNew);
var hasHandle = false;
try
{
hasHandle = mutex.WaitOne(timeout_ms, false);
if (hasHandle == false)
return null;
else
return mutex;
}
catch (AbandonedMutexException)
{
mutex.ReleaseMutex();
mutex.Close();
mutex.Dispose();
return null;
}
catch (Exception err)
{
return null;
}
}
}
}
这里我将如何使用上面的类。下面的代码用于定期过程(通过windows scheduler进行调度),因此,如果有时出错不是问题(下一次运行将完成此工作),重要的是不存在争用条件或死锁
using ( var mutex = MutexManager.TryRegister("procedureName") )
{
...DO WORK
}
互斥锁由单个进程“拥有”,如果进程崩溃或关闭,互斥锁将被释放。
如果进程崩溃,Mutex被释放,那么它被认为是“放弃的”,这是一种信号,表明原始进程不再拥有它——但也没有明确释放它。
在您的问题或代码中,我不太理解的是如何处理废弃的互斥体。只有在先前没有放弃的情况下,助手才会返回互斥对象。如果它被放弃,代码将成功检索互斥体,然后释放它并返回,而根本不提供互斥体。
这可能是目的,但从问题的措辞来看,这有点难以理解。如果帮助程序打算重置并返回互斥锁,则放弃的MutexException
的处理看起来不正确,因为它将始终返回null。