2013-09-23 63 views
2

有這個類,它允許在一個線程中將數據寫入流中並在多個線程中讀取。C#併發列表訪問

它支持流式傳輸的主要目的,網絡或音頻流,讀取它並在多個線程中進行處理,從而可以隨時發送數據。

http://www.codeproject.com/Articles/345105/Memory-Stream-Multiplexer-write-and-read-from-many?msg=4665022#xx4665022xx

MemoryStreamMultiplexer由組塊,並存儲寫入的數據塊到List<byte[]> _Buffer變量。

這_buffer然後被傳遞到MemoryStreamReader這樣的:

new MemoryStreamReader(_Buffer, dataReady, finished); 

MemoryStreamReader讀出存儲在此_buffer列表中的一個我的一個字節[]數組,檢查數據是否存在

if (_bufferIndex < _bufferList.Count) 
{ 
    return ReadInternal(buffer, offset, count); 
} 

ReadInternal得到_Buffer列表中的下一個緩衝區,然後將其讀取

byte[] currentBuffer = _bufferList[_bufferIndex]; 

現在,這裏是問題:隨機,currentBuffer變爲null,導致NullReferenceException稍後。

在調試中,當currentBuffer聲明爲null時,如果我檢查_bufferList [_bufferIndex]中的值 - 返回有效數組。所以這似乎是一些內存或併發問題。

我的想法是,有些時候List決定改變它的容量,重新分配內部數組。雖然我們仍在讀取List,但它會返回null,因爲內存地址已經更改,但尚未將數據複製到其中。

問題是 - 如何解決這個問題?

回答

2

這是一個稍微擴展的producer-consumer problem。因爲你正在使用C#(gc,內存將自動釋放)我建議創建每個使用單獨的同步隊列,然後發佈相同的數據數組到每個隊列。由於數據只有在被推入後纔會被讀取,因此多線程同時訪問它是完全安全的。

使用ConcurrentQueue可以節省您對同步的擔心,從而爲您節省大量工作。

+0

感謝您的想法。對於少量數據可能是值得的,但是對於一個流 - 任何大小的數據都可以通過實現來傳遞。因此,如果我們將相同的數據陣列發佈到多個隊列中,則會多次增加內存消耗,並且如果初始數據較大,可能會導致嚴重問題 – AAverin

+0

此外,應該使用ConcurrentQueue 而不是同步隊列。 – dcastro

+0

另外,請記住,例如,如果我們正在閱讀網絡,_Buffer可能會隨時更改。因此,將數據推送到ConcurentQueue不是一種選擇 - 我們將在沒有任何更新的情況下獲得陳舊的數據 – AAverin