So, imagine the following situation:
The code runs in the background thread. It captures the lock and then launches MethodA .
MethodC is called, and MethodA is in the middle of its work. MethodA expects the lock to be free, blocking the user interface thread until this happens.
The background thread ends with MethodA and proceeds to calling MethodB in the user interface thread. MethodB cannot work until all previous elements of the message queue are complete.
MethodC is at the top of the message queue, waiting for MethodB end, and MethodB is in the queue until MethodC ends. They are both waiting for each other, which is a dead end.
So how do you solve this problem? What you really need is some way to βwaitβ on the lock, without actually blocking the stream. Fortunately (in .NET 4.5) this is easy to do thanks to the parallel task library. (I'm waiting in quotation marks because we actually do not want to wait, we just want to execute MethodC as soon as the lock is released without actually waiting / blocking the current thread.)
Instead of using object for MyLock use:
private static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
Now for MethodC you can do:
public async Task MethodC() //you can change the signature to return `void` if this is an event handler { try { await semaphore.WaitAsync(); //Do stuff } finally { semaphore.Release(); } }
The key point here is that since we are await when the semaphore is actually free, we are not blocking the current thread, which allows another background task to marshal MethodB on the MethodB thread, terminate the method, release the semaphore, and then enable this method.
Your other code is not needed (but it can still, if you want) use asynchronous wait on the semaphore; blocking the background thread is not almost the same problem, so the only key change is to use a semaphore instead of lock :
public void Bar() { try { semaphore.Wait(); MethodA(param1, param2); MyDelegate del = new MyDelegate(MethodB); if (this.IsHandleCreated) this.Invoke(del); } finally { semaphore.Release(); } }
Servy source share