【问题标题】:C# concurrent List accessC#并发列表访问
【发布时间】:2013-09-23 23:37:56
【问题描述】:

有这个类,允许在一个线程中将数据写入流并在多个线程中读取。

它支持流媒体的主要目的,例如。网络或音频流,读取它并在多个线程中处理,允许数据随流传输。

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 列表中的 byte[] 数组,检查数据是否存在

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,因为内存地址已经更改,但尚未将数据复制到其中。

问题是 - 如何解决这个问题?

【问题讨论】:

    标签: c# multithreading list concurrency


    【解决方案1】:

    这是一个稍微扩展的producer-consumer problem

    由于您使用的是 C#(gc,内存将自动释放),我建议使用单独的同步队列创建每个消费者,然后将相同的数据数组发布到每个队列。由于数据只有在推送后才会被读取,因此多个线程同时访问它是完全安全的。

    使用 ConcurrentQueue 可以让您不必担心同步问题,从而为您节省大量工作。

    【讨论】:

    • 感谢您的想法。少量数据可能值得,但对于流 - 任何大小的数据都可以通过实现传递。所以,如果我们将同一个数据数组发布到多个队列中——它会多次增加内存消耗,并且如果初始数据很大,可能会导致严重的问题
    • 另外,应该使用 ConcurrentQueue 而不是同步队列。
    • 另外,请记住,_Buffer 中的内容可能会即时更改 - 例如,如果我们正在阅读 Network。因此,将数据推送到 ConcurentQueue 不是一种选择——我们将在没有任何更新的情况下获得陈旧的数据
    • @AAverin 我的想法是在收到整个块后推送数据。我不知道这是否可能。
    • @dcastro 想知道为什么?您的评论没有任何理由。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 2011-04-25
    • 2023-04-08
    相关资源
    最近更新 更多