How can I find from mutex handle in C# that a mutex is acquired?
When mutex.WaitOne(timeout)
timeouts, it returns false
. However, how can I find that from the mutex handle? (Maybe using p/invoke.)
UPDATE:
public class InterProcessLock : IDisposable
{
readonly Mutex mutex;
public bool IsAcquired { get; private set; }
public InterProcessLock(string name, TimeSpan timeout)
{
bool created;
var security = new MutexSecurity();
security.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
mutex = new Mutex(false, name, out created, security);
IsAcquired = mutex.WaitOne(timeout);
}
#region IDisposable Members
public void Dispose()
{
if (IsAcquired)
{
mutex.ReleaseMutex();
IsAcquired = false;
}
}
#endregion
}
Currently, I am using my own property IsAcquired
to determine whether I should release a mutex. Not essential but clearer, would be not to use a secondary copy of the information represented by IsAcquired
property, but rather to ask directly the mutex whether it is acquired by me. Since calling mutex.ReleaseMutex()
throws an exception if it is not acquired by me.
(By acquired state I mean that the mutex is in not-signaled state when I am owning the mutex.)
(EDIT: I have added IsAcquired = false;
thanks to mattdekrey's post.)
The reason there is no clean way to do this is because it is not a good idea and the reason is because race conditions are -very- easy to introduce when you rely on this type of logic. So your design needs to change.
First, you should not acquire a lock in a constructor. Turn this class into a factory that returns a properly initialized mutex object. That way you can know if you acquired the lock or not.
DO NOT rely on Dispose to release locks, this is asking for deadlock ridden code that is hard to maintain. Use a try/finally block to ensure it is released.
Timeouts are a bit sketchy. Only use timeouts when not acquiring the lock would be considered normal operation. Not being able to acquire the lock is usually a bug and merely avoiding it with timeouts hides the bug. If you need timeouts, consider using an event (maybe AutoResetEvent), this may be more appropriate.