Thursday, March 15, 2007

Object synchronization method was called from an unsynchronized block of code

Despite the tremendous improvement in .NET compared to anything Microsoft released earlier, Microsoft still lags behind where Java was with ease of use of multithreading. .NET multithreading is great and easy to use - but only if you already know multithreading. There are hundreds of different ways to handle synchronization, and some work well, some work poorly, and in my opinion, some don't work at all. All this makes me wish they would just give me Dijkstra's semaphore (P and V methods) and let me build my own stuff on top of it.

Today, I tried to Google an error I got: "System.ApplicationException: Object synchronization method was called from an unsynchronized block of code." Immediately (based on the error message), I thought I either needed to mark the method, class or assembly as needing to use synchronization somehow (either attributes or compiler switches came to mind). This was odd, because I didn't remember ever needing to do this before (well, not since the COM apartment threading mess anyway).

You would think this would be easy to find. I went through every entry on the first 3 Google pages (60 entries). Lots of people had this problem, but most answers were:
  • use Monitors instead of synchronization object X-with no explanation of why.
  • Do you really need to do this? - I always hate this answer when someone posts a legitimate technical question. The question still has merit, regardless of whether the author really the answer or not.
  • Use Google to find the answer - I hate this too. I am convinced it will eventually destroy Google (any search will eventually only yield thousands of pages telling you to search Google).

Anyhow, I gave up on Google and went back to my code, and the answer was really simple. All I did was release the Mutex before I acquired it (I left out the line of code Mutex.WaitOne).

I guess I am posting this for 2 reasons

  • I don't want anyone else looking through 60 pages of worthless Googling (although I doubt this blog will get ranked in the top 60 anyway).
  • This is a really bad error message. Every time you enter a synchronized block of code, you do so by calling an object synchronization method from an unsynchronized block of code. What it should say is "Invalid Object synchronization method called from an unsynchronized block of code" or simply "Invalid Object synchronization method call". This would make finding the answer easy.

22 Comments:

Blogger jim_h said...

You're so right about Google losing its usefulness.

Also - 10 years (and more) ago, Usenet was vastly more useful than it is today. Then, it was a Q&A forum. Today, it's a great way to find other people all over the planet who have the same problem you do - but no solution. The endless posting and re-posting of questions, without first searching for an answer, turned it into InfoPulp.

1:46 PM  
Anonymous Anonymous said...

Thank you. You're actually the top hit on Live Search for:

"Object synchronization method was called from an unsynchronized block of code." + Mutex

This error message sucks. I had to wade, but you saved me from more than 10 pages of it. :)

5:22 PM  
Anonymous RoryA said...

3 months on and you're still Google's number 1 result ;)
Thanks for the help. The mutex was my first guess since I recently changed code regarding it but your post confirmed it without me having to dig through all my source.

11:46 PM  
Blogger TechNeilogy said...

Brad, you just saved me about a hour of trial and error!

The funny thing is, I think I've encountered this before; you're right, the error message is so obtuse it didn't even remind me of the last time I saw it.

2:53 PM  
Anonymous Anonymous said...

Let's just say I definately love you for writing this down.

12:49 PM  
Blogger andyctedd said...

I subscribe everything that has been said above (or below actually, anyway you get it).

4:58 PM  
Blogger Pramod said...

Brad, You have done a great job.
ThanX

1:22 AM  
Anonymous Anonymous said...

Hey Brad, by any chance are you using a value type (int, decimal, etc...) inbetween Monitor.Enter() and Moniter.Exit()?

Apparantly some folks at Microsoft thought thread safing things would only ever be useful for objects, not for value types. Go figure... I suppose we are to interpret this as BRILLIANT!

This from MSDN URL: http://msdn2.microsoft.com/en-us/library/hf5de04k(VS.71).aspx


Monitor locks objects (that is, reference types), not value types. While you can pass a value type to Enter and Exit, it is boxed separately for each call. Since each call creates a separate object, Enter never blocks, and the code it is supposedly protecting is not really synchronized. In addition, the object passed to Exit is different from the object passed to Enter, so Monitor throws SynchronizationLockException with the message "Object synchronization method was called from an unsynchronized block of code."

4:03 PM  
Blogger Ralph said...

Hi! Thanks 'anonymous'. A bit of valueable insight there.. :$

I suddenly had this problem occur in a .NET 1.1 application that used to work fine. The code was used as a callout library for MS CRM 3, and after an upgrade to CRM 4 (and the required Win2003 SP2) I got the error above.

As it turned out, I used an int to synchronize, which has worked fine before. I added an extra
private object whatever = new object();
and locked on that. Now the application runs like a charm again.

5:15 AM  
Blogger praveen said...

Thanks a lot... also to the anonymous who suggested the object stuff.

3:07 AM  
Anonymous Mariatta said...

Thank you so much.
I have the same exception, and the problem was exactly what you described: I left out the mutex.WaitOne() due to copy-pasting.

12:04 PM  
Blogger Mrt said...

Thanks for your post, it was helpful.
I come here by googleing, and this page was in top ten pages...

10:55 PM  
Anonymous Regina said...

People should read this.

5:27 AM  
Anonymous Jamil said...

Well thanks for the post and Google did land me on your page saved the pain you went through. I agree msdn should have some more information about this error message

11:00 PM  
Blogger jim_h said...

Those "why do you think you need to do that" replies really frost me too.

1:59 PM  
Blogger george said...

really, it is actually quite obvious. all you should do is read the documentation or realize that, gee, the exception occured on the ReleaseMutex() method.

10:56 PM  
Anonymous Jared C. said...

Thanks! Top Google search result for: "Object synchronization method was called from an unsynchronized block of code."

6:15 PM  
Anonymous Anonymous said...

Well, I just encountered this problem.

Turns out the code I've been using is using a static Mutex, but is it instantiated in a public constructor of the XX class I'm using.

I've moved the instantiation of the Mutex to a static initializer block instead and have yet to encounter the issue again (doesn't mean it's gone though ;)).

4:21 AM  
Blogger ruslan said...

Since it's Google's #1 hit I will answer here.

I had following code:

DateTime temp;
if (Monitor.TryEnter(temp))
{
temp = DateTime.Now;
Monitor.Exit(temp);
}

I was getting an exception "Object synchronization method was called from an unsynchronized block of code" because I was replacing whole object (because it's struct) and it was no longer locked.

12:02 PM  
Anonymous Raj said...

What if I am getting this error without Mutex? Been pulling hair for a while but cant get it.

12:55 PM  
Blogger Bryan Murphy said...

In my case, I wasn't checking the boolean return value of WaitOne() and was assuming it would throw an exception when it timed out. Of course, it threw no exception and when I tried to release the mutex it would then fail.

Don't forget, WaitOne returns a boolean!

2:22 PM  
Blogger TheBunyip said...

On the subject of getting this exception when calling ReleaseMutex on a Mutex object, the simple answer is that the .NET Mutex class enforces 'thread identity'. This is stated in the MSDN docs for the Mutex class, but still seems odd to me.

Basically, you have to call ReleaseMutex on the same thread that you called WaitOne on.

It turns out you often want to use Monitor instead of a Mutex. This seems markedly different to lower-level Win32 mutexes (which, as I remember, have no such thread affinity).

1:53 AM  

Post a Comment

<< Home