2012-10-08 38 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:沒關係。謝謝。 –