Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object synchronization method was called from an unsynchronized block of code. Exception on Mutex.Release()

I have found different articles about this exception but none of them was my case. Here is the source code:

class Program {      private static Mutex mutex;     private static bool mutexIsLocked = false;     static void Main(string[] args)     {          ICrmService crmService =              new ArmenianSoftware.Crm.Common.CrmServiceWrapper(GetCrmService("Armsoft", "crmserver"));         //Lock mutex for concurrent access to workflow         mutex = new Mutex(true, "ArmenianSoftware.Crm.Common.FilterCtiCallLogActivity");         mutexIsLocked = true;          //Create object for updating filtered cti call log         ArmenianSoftware.Crm.Common.FilterCtiCallLog filterCtiCallLog =             new ArmenianSoftware.Crm.Common.FilterCtiCallLog(crmService);         //Bind events         filterCtiCallLog.CtiCallsRetrieved += new EventHandler<ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs>(filterCtiCallLog_CtiCallsRetrieved);          //Execute filter         try         {             filterCtiCallLog.CreateFilteredCtiCallLogSync();         }         catch (Exception ex)         {             throw ex;         }         finally         {             if (mutexIsLocked)             {                 mutexIsLocked = false;                 mutex.ReleaseMutex();             }         }     }      static void filterCtiCallLog_CtiCallsRetrieved(object sender,          ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs e)     {         tryasasas         {             if (mutexIsLocked)             {                 mutexIsLocked = false;                 mutex.ReleaseMutex();             }         }         catch (Exception ex)         {             throw ex;         }     } } 

filterCtiCallLog.CreateFilteredCtiCallLogSync(); function executes requests to server, and raises some events, one of which is CtiCallsRetrieve event. And I need to release the mutex when this event is fired. But on calling the mutex.Release() function exception is thrown. CreateFilteredCtiCallLogSync works synchronously. What is the problem?

like image 731
kyurkchyan Avatar asked Jan 26 '12 11:01

kyurkchyan


2 Answers

Keeping a bool around that indicates that the mutex is owned is a grave mistake. You are not making the bool thread-safe. You got into this pickle because you are using the wrong synchronization object. A mutex has thread-affinity, the owner of a mutex is a thread. The thread that acquired it must also be the one that calls ReleaseMutex(). Which is why your code bombs.

You in all likelihood need an event here, use AutoResetEvent. Create it in the main thread, call Set() in the worker, WaitOne() in the main thread to wait for the worker to complete its job. And dispose it afterwards. Also note that using a thread to perform a job and having your main thread wait for its completion is not productive. You might as well have the main thread do the job.

If you are actually doing this to protect access to an object that's not thread-safe (it isn't clear) then use the lock statement.

like image 158
Hans Passant Avatar answered Oct 08 '22 05:10

Hans Passant


Another reason why this exception may occur:

if (Monitor.TryEnter(_lock)) {     try     {         ... await MyMethodAsync(); ...     }     finally     {         Monitor.Exit(_lock);     } } 

I get this exception on Monitor.Exit when after 'await' another thread continues execution.

Edit: Use SemaphoreSlim, because it doesn't require releasing thread to be the same.

like image 21
Igor Toropov Avatar answered Oct 08 '22 04:10

Igor Toropov