We have a legacy VB6 executable that can run multiple instances. We'd like certain jobs only allow one concurrent instance.
It seems that an OS Mutex is a perfect fit, as this is a legacy app all new code must be written in C# and accessed over interop.
I have created a class that will acquire:
public bool AcquireLock(string JobId)
{
// get application GUID as defined in AssemblyInfo.cs
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
appGuid = appGuid + JobId;
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
bool mutexExists = false;
var mutex = new Mutex(true, mutexId, out mutexExists);
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
mutex.SetAccessControl(securitySettings);
return mutexExists;
}
And release locks:
public bool ReleaseLock(string JobId)
{
// get application GUID as defined in AssemblyInfo.cs
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
appGuid = appGuid + JobId;
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
var mutex = Mutex.OpenExisting(mutexId);
mutex.ReleaseMutex();
return true;
}
All seems to work well enough until I try to release the lock:
[TestMethod()]
public void ReleaseLockTest()
{
var target = new MutexConcurrencyHelper();
var jobId = RandomUtils.RandomString(8, true);
var expected = true;
bool actual;
actual = target.AcquireLock(jobId);
Assert.AreEqual(expected, actual);
target.ReleaseLock(jobId);
var expected1 = true;
bool actual1;
actual1 = target.AcquireLock(jobId);
Assert.AreEqual(expected1, actual1);
}
The second attempt at gaining a lock find the lock already in place. Why does this lock not release?