【问题标题】:SynchronizationLockException after await等待后的 SynchronizationLockException
【发布时间】:2012-10-08 03:25:04
【问题描述】:

我有一个名为HandleMessage 的方法,启动了一个新线程来处理消息。如果锁对象被成功获取,则处理它。否则将消息放入队列。 SynchronizationLockException 总是被抛出 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);
            }
        });
    }

【问题讨论】:

  • 副手,似乎 TPL 数据流更合适,因为您的 HandleMessage 可以只发布到块而不是包含此逻辑?

标签: c# multithreading windows-8 async-await


【解决方案1】:

如您所见,Monitor.Enter/Exit 是线程仿射的。

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 不过,这会改变行为。以前,您可以确定不会同时处理两条消息,但现在可以了。你的情况可以吗?
    猜你喜欢
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多