Cheng Chen
Cheng Chen

Reputation: 43523

SynchronizationLockException after await

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

Answers (2)

James Manning
James Manning

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

Cheng Chen
Cheng Chen

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

Related Questions