Using Named Mutex

2019-02-25 09:43发布

问题:

I have two instances running of same Windows Service. They check the health of each other and report if any issue is found. I have a critical job that needs to be performed so I am running it with a fail-over approach, it runs in Master, and if Master is not responding it runs in slave. This job needs to communicate over a specific serial port, I am trying to use Mutex to check for race condition. I dont have access to production, so before deploying I want to make sure my approach is fine. So please suggest if my use of Mutex is fine for the given case.

if (iAmRunningInSlave)
{
   HealthClient hc = new HealthClient();
   if (!hc.CheckHealthOfMaster())
      return this.runJobWrapper(withMutex, iAmRunningInSlave);
   else
      return true; //master is ok, we dont need to run the job in slave
}
return this.runJobWrapper(withMutex, iAmRunningInSlave);

And then in runJobWrapper

bool runJobWrapper(bool withMutex, bool iAmRunningInSlave)
{
   if (!withMutex)
      return this.runJob(iAmRunningInSlave); //the job might be interested to know 
   Mutex mutex = null;
   string mutexName = this.jobCategory + "-" + this.jobTitle; //this will be unique for given job
   try
   {
      mutex = Mutex.OpenExisting(mutexName);
      return false; //mutex is with peer, return false which will re-trigger slave
   }
   catch
   {
      try
      { //mean time mutex might have created, so wrapping in try/catch
         mutex = new Mutex(true /*initiallyOwned*/, mutexName);
         return this.runJob(iAmRunningInSlave); //the job might be interested to know where I am running
      }
      finally
      {
         if (null!=mutex) mutex.ReleaseMutex();
      }
      return false;
   }
}

回答1:

I had a similar issue recently.

The design of the Mutex class is a bit weird/different from the normal classes in .NET.

Using OpenMutex to check for an existing Mutex is not really nice as you have to catch an exception.

A better approach is to use the

Mutex(bool initiallyOwned, string name, out bool createdNew) 

constructor, and check the value returned by createdNew.



回答2:

You don't look to check the return value from runJobWrapper anywhere - is this intentional? It is not obvious what the return value actually means anyway. Also you really shouldn't catch each any every exception that OpenExisiting could possibly throw - Out of memory? Stack overflow? etc. etc. Just catch the one you mean to handle correctly.

Also your code looks to be somewhat fragile - I wouldn't be surprised if you have race conditions.



回答3:

I noticed that mutex.ReleaseMutex() was not releasing the mutex immediately..I had to call GC.Collect()



标签: c# mutex