Reputation: 43523
I have a method called HandleMessage
, a new thread is started to handle the message. If the lock object is fetched successfully, then handle it. Otherwise put the message in the queue. A SynchronizationLockException
is always thrown at Monitor.Exit(o)
since after await
the context isn't in the original thread any more. What's the correct way to implement?
public void HandleMessage(string message)
{
Task.Factory.StartNew(async delegate
{
if (Monitor.TryEnter(o))
{
try
{
do
{
await HandleMessageAsync(message);
}
while (queue.TryDequeue(out message));
}
finally
{
Monitor.Exit(o);
}
}
else
{
queue.Enqueue(message);
}
});
}
Upvotes: 2
Views: 381
Reputation: 13589
As you've noticed, the Monitor.Enter/Exit are thread-affine.
In their series on creating async-friendly coordination primitives, Stephen includes an AsyncLock that should be what you're looking for AFAICT.
Upvotes: 4
Reputation: 43523
Now I found the sync lock object o
here is useless, because my queue
is concurrent. At last the solution is:
public void HandleMessage(string message)
{
Task.Factory.StartNew(async delegate
{
while (queue.TryDequeue(out message));
{
await HandleMessageAsync(message);
}
});
}
This resolves the problem. But it doesn't answer the question per-se.
Upvotes: 1