Monitor
has thread-affinity. You can't exit it from a different thread.
But it's not clear what you're trying to do here anyway. You're already in an async method, calling another async method. Just use await
- just setup an synchronization context to allow you to use await
properly in a console application. Or, use Task.Wait
if you're not worried about deadlocks :)
As for Monitor.Wait
, it doesn't do what you think it does. The wait is for a signal, not for the monitor being exited. For example:
static readonly object syncObject = new object();
void Thread1()
{
lock (syncObject) Monitor.Wait(syncObject);
}
void Thread2()
{
lock (syncObject) Monitor.Pulse(syncObject);
}
Both methods are executed on separate threads in this scenario. If Thread1
runs first, it will take the lock, wait for a signal (this exits the lock until the signal is presented) and reacquire the lock after the signal is given. Thread1
provides the signal using the Monitor.Pulse
method. Note that in both cases, the lock is taken on a single thread, and exited on the same thread.
This mechanism isn't very easy to use properly, and is somewhat slow, so you're not going to see it much.
Also, the threads used by Task.Run
aren't yours. It's usually undesirable to use blocking code on thread-pool threads - make sure you understand the trade-offs your making. Even more importantly, tasks have no thread-affinity - so using a thread-affine synchronization primitive like a monitor is rather adventurous :) In your case, even if you took the lock inside the Task.Run
rather than the outside, it would be possible for the Monitor.Exit
to fail, since you might have gotten a different thread after the await
.
Don't forget that the trickiest part about multi-threading isn't that it just doesn't work - it's that it has an ugly tendency to mostly work for the most part, and fail in weird scenarios (that happen all the time in practice, mind you). Testing isn't quite enough to give you much confidence in how a multi-threaded piece of code behaves in practice. All you get is tons of tiny, almost impossible to reproduce bugs. You got lucky here - your code fails reliably; that certainly isn't the case with most multi-threading issues :)
Joe Albahari's introduction to threading is a huge help for multi-threaded programming of any kind. I highly recommend reading through the whole of it at least once. Keep it in your bookmarks for future reference :)