2012-01-26 64 views
0

我正在開發一個應用程序模擬一個網絡組成的交換消息的節點數量。我嘗試用Queue模擬傳輸通道,每個節點都可以放置一條消息。然後,另一個實體接管該消息並將其傳遞到指定的節點。然後,當消息隊列爲空閒一段時間,比如說X,即沒有新消息添加到隊列X毫秒時,我想用信號(帶一個事件)傳輸階段結束。奇怪的C#線程ThreadInterrupted異常

我明白我的情況遵循消費者/生產者範例。到目前爲止,我也做了以下內容:

public class Com<T> 
{ 
    private Thread dispatcher; 
    private Queue<T> queue; 
    private int waitTime; 
    private Object locker; 
    private Timer timer; 
    public event EventHandler EmptyQueueEvent; 

    public Com() 
    { 
     queue = new Queue<T>(); 
     locker = new Object(); 
     waitTime = X; 
     timer = new Timer(FireEmpty, null, Timeout.Infinite,Timeout.Infinite); 
     dispatcher = new Thread(Serve); 
     dispatcher.IsBackground = true; 
        dispatcher.Start(); 
    } 

    private void Serve() 
    { 
     while (true) 
     { 
      try 
      { 
       if (queue.Count == 0) 
       { 
        timer.Change(waitTime, 0); 
        Thread.Sleep(Timeout.Infinite); 
       } 
      } 
      catch (ThreadInterruptedException) 
      { 
      } 
      while (queue.Count != 0) 
      { 
       lock (locker) 
       { 
        deliver(queue.Dequeue()); 
       } 
      } 
     } 
    } 

    private void deliver(T item) 
    { 
     // Do stuff 
    } 

    public void Add(T item) 
    { 
     timer.Change(Timeout.Infinite, Timeout.Infinite); 
     lock (locker) 
     { 
      queue.Enqueue(item); 
     } 
     dispatcher.Interrupt(); 
    } 

    private void FireEmpty(object o) 
    { 
     //Fire Event 
    } 
} 

但是,運行我的模擬證明了我的同步是不夠的,因爲我有時會得到一個「ThreadInterruptedException」試圖離隊我的消息(在方法即成() )。請注意,每次我運行模擬時都不會發生異常,但很少:大約每850-1000次執行一次(我正在迭代運行執行)。

有沒有人知道我的代碼有什麼問題? :)

回答

1

在嘗試獲取Queue計數之前,您嘗試過鎖定嗎?如:

private void Serve() 
    { 
     while (true) 
     { 
      try 
      { 
       int count = 0; 
       lock(locker) 
        count= queue.Count; 
       if (count == 0) 
       { 
        timer.Change(waitTime, 0); 
        Thread.Sleep(Timeout.Infinite); 
       } 
      } 
      catch (ThreadInterruptedException) 
      { 
      } 
      while (queue.Count != 0) 
      { 
       lock (locker) 
       { 
        deliver(queue.Dequeue()); 
       } 
      } 
     } 
    } 

在您嘗試計算項目數的同時,可能會調用添加。另外,如果您使用的是.net 4.0,您可能需要考慮System.Collections.Concurrent的其中一個集合。

** UPDATE **

我只是在仔細看看你的代碼,並有一個「噢咄」的時刻。你應該得到一個ThreadInterruptException,因爲你打電話delegate.Interrupt()。檢查MSDN documentation。我認爲你需要做的是使用類似於ManualResetEvent的東西,而不是在該事件中調用Interrupt()WaitOne()

** UPDATE2 ** 下面是一些示例代碼,包括我的其他鎖定的建議,以及(在GIST): https://gist.github.com/1683547

+0

+1阻止集合。 –

+0

@編碼大猩猩:那也行不通;我在確切點得到了完全相同的異常:(感謝提示雖然! – Artem

+0

@ user1171442查看我的更新 – CodingGorilla