It seems that Monitor doesn't work as expected in WinRT store applications. I have the following code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var tasks = Enumerable.Range(0, 10).Select((i)=>new Task(DoWork)).ToArray();
foreach (var task in tasks)
{
task.Start();
}
Task.WaitAll(tasks);
}
static object lockObject = new Object();//typeof(MainPage)
protected async void DoWork()
{
bool taken =false;
Monitor.Enter(lockObject, ref taken);
Debug.WriteLine("In");
await Task.Delay(1000);
Debug.WriteLine("Out");
if (taken) Monitor.Exit(lockObject);
}
In the output window I see:
In
In
In
In
In
In
In
Out
Out
Out
Out
Out
Out
Out
In
Out
A first chance exception of type 'System.Threading.SynchronizationLockException' occurred in App4.exe
Which mean that Monitor is not locking the critical area. Does anybody has a clue what I'm doing wrong?
You're effectively trying to use:
lock (lockObject)
{
await Task.Delay(1000);
}
... except that the C# compiler wouldn't allow you to do that, because it would be broken. By the time your await
expression completes, you can be on a different thread - so when you call Monitor.Exit
, you may well not be on the same thread as you acquired the lock in... hence the exception.
I suggest that you change your logging to show:
In
, what thread you're on and the value of taken
afterwards (you'll probably see that some tasks haven't successfully taken the monitor, because another thread owns it - but see below)Monitor.Exit
, what thread you're onIt's not clear what you're trying to achieve, but using Monitor
here is almost certainly the wrong approach.
Also note that because multiple tasks can all execute on the same thread (not at the same time, but you're "giving up" the thread with await) and because monitors are reentrant (one thread can acquire a monitor multiple times) you may well see multiple tasks acquiring the monitor.
It's important that you understand why this doesn't work - and that you understand that a thread isn't the same as a task. Then you can try to start working out how to actually achieve what you want, which almost certainly isn't via Monitor
.