2

我有一个名为 的方法HandleMessage,启动了一个新线程来处理消息。如果锁对象被成功获取,则处理它。否则将消息放入队列。ASynchronizationLockException总是被抛出,Monitor.Exit(o)因为在await上下文不再在原始线程中之后。正确的实施方式是什么?

    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);
            }
        });
    }
4

2 回答 2

4

正如您所注意到的,Monitor.Enter/Exit 是线程仿射的。

在他关于创建异步友好协调原语的系列中,Stephen 包含了一个AsyncLock,它应该是您正在寻找的 AFAICT。

于 2012-10-08T04:18:48.470 回答
1

现在发现object o这里的同步锁是没用的,因为myqueue是并发的。最后解决办法是:

public void HandleMessage(string message)
{
    Task.Factory.StartNew(async delegate
    {
        while (queue.TryDequeue(out message));
        {
           await HandleMessageAsync(message);
        }
    });
}

这解决了问题。但它本身并没有回答这个问题。

于 2012-10-08T03:40:19.470 回答