2013-09-23 42 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