2012-10-08 41 views
1

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

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); 
      } 
     }); 
    } 
+0

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

回答

3

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

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

1

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

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

这就解决了这个问题。但它并不回答这个问题。

+0

虽然这改变了行为。在此之前,您可以确定两条消息不会同时处理,但现在有可能。你的情况好吗? – svick

+0

@svick:没关系。谢谢。 –