2011-05-04 68 views
2

比方說,我有一個列表,並將數據從一個namedpipe流式傳輸到該列表。命名管道列表,而能夠閱讀或使用該列表?

假設的例子:

private void myStreamingThread() 
{ 
    while(mypipe.isconnected) 
    { 
     if (mypipe.hasdata) 
      myList.add(mypipe.data); 
    } 
} 

然後在另一個線程我需要閱讀該列表例如每1000毫秒:

private void myListReadingThread() 
{ 
    while(isStarted) 
    { 
     if (myList.count > 0) 
     { 
      //do whatever I need to. 
     } 
     Thread.Sleep(1000); 
    } 
} 

在這裏,我的首要任務是能夠讀取列表中每1000毫秒並根據列表的需要做任何事情,但同時能夠從管道獲取來自管道的新數據非常重要。

什麼是一個很好的方法來與此?

忘了提我綁在.NET 3.5

回答

1

我會建議使用ConcurrentQueue(http://msdn.microsoft.com/en-us/library/dd267265.aspx)。如果您使用簡單的列表> <>那麼您將會遇到很多線程問題。

另一種做法是使用名爲outstandingWork的互斥體,並等待它,而不是Thread.Sleep()。然後,當你入職一些工作時,你會發揮出色的工作。這意味着你在沒有工作的情況下睡覺,但立即開始處理工作,而不是在整個1秒鐘內完成睡眠。

編輯

由於@Prix指出的那樣,您使用的是.NET 3.5。所以你不能使用ConcurrentQueue。使用隊列類與以下

Queue<Work> queue; 
AutoResetEvent outstandingWork = new AutoResetEvent(false); 

void Enqueue(Work work) 
{ 
    lock (queue) 
    { 
     queue.Enqueue(work); 
     outstandingWork.Set(); 
    } 
} 

Work DequeMaybe() 
{ 
    lock (queue) 
    { 
     if (queue.Count == 0) return null; 
     return queue.Dequeue(); 
    } 
} 

void DoWork() 
{ 
    while (true) 
    { 
     Work work = DequeMaybe(); 
     if (work == null) 
     { 
      outstandingWork.WaitOne(); 
      continue; 
     } 
     // Do the work. 
    } 
} 
+0

@理查德,確實很棒,但它說.Net 4 – Prix 2011-05-04 23:09:28

+0

謝謝@Prix,我會編輯。 – 2011-05-04 23:11:23

+0

使用互斥體不會在某些時候失敗,因爲管道可以隨時發送新數據,如果它一次發送,我正在讀取列表,它將在管道寫入時失敗,反之亦然否?並感謝您的回覆;) – Prix 2011-05-04 23:11:32

2

我會推薦使用帶鎖的Queue

Queue<string> myQueue = new Queue<string>(); 

private void myStreamingThread() 
{ 
    while(mypipe.isconnected) 
    { 
     if (mypipe.hasdata) 
     { 
      lock (myQueue) 
      { 
       myQueue.add(mypipe.data); 
      } 
     } 
    } 
} 

如果要每1000毫秒清空隊列,請不要使用Thread.Sleep。改爲使用timer

System.Threading.Timer t = new Timer(myListReadingProc, null, 1000, 1000); 


private void myListReadingProc(object s) 
{ 
    while (myQueue.Count > 0) 
    { 
     lock (myQueue) 
     { 
      string item = myQueue.Dequeue(); 
      // do whatever 
     } 
    } 
} 

請注意,上面假設隊列只被一個線程讀取。如果多個線程正在讀取,則存在競態條件。但上述內容將與單個讀者和一個或多個作者一起工作。

+1

這有一個競爭條件。您正在測試鎖外的Count。所以count可以大於零,但是當獲得鎖定時,隊列可能是空的! – 2011-05-04 23:21:46

+0

@Richard:如果你在最後閱讀了評論,我提到了這種競爭狀況,並指出一個閱讀器可以。對於多個閱讀器,只需在鎖內添加另一個「Count」檢查即可。 – 2011-05-04 23:37:45

+0

非常感謝,它似乎工作得很好,因爲我只有一個讀者。 – Prix 2011-05-05 01:35:42