ConcurrentQueue<byte[]> 中的所有项目都相同

All items in ConcurrentQueue<byte[]> are identical

我有一个 NetworkStream 用于从另一个程序获取数据。数据以 Byte[64] 的形式到达,然后我将其排队到 ConcurrentQueue,以便另一个线程可以出队以供稍后分析。 队列被实例化:

ConcurrentQueue<byte[]> fifo = new ConcurrentQueue<byte[]>();

然后我将所有发送的数据加入队列:

Byte[] bytesIn = new Byte[64];
int i;
while ((i = stream.Read(bytesIn, 0, bytesIn.Length)) != 0)
{
    fifo.Enqueue(bytesIn);
}

如果我然后(在调试期间)查看 fifo 中的数据,结果发现包含的每个字节 [64] 都与最新的 bytesIn 相同。我如何确保我添加到 fifo 的数组是值而不是指针(如果这是正确的术语)?

将数组的 copy 加入队列。您可以为此使用 ToArray 扩展名。

while ((i = stream.Read(bytesIn, 0, bytesIn.Length)) != 0)
{
    var received = bytesIn.Take(i).ToArray();
    fifo.Enqueue(received);
}

我还使用 Take 到 trim 缓冲区,并仅复制接收到的字节。

或者,正如@hvd 在评论中所建议的那样,使用 Array.Copy 会更快

while ((i = stream.Read(bytesIn, 0, bytesIn.Length)) != 0)
{
    var received = new byte[i];
    Array.Copy(bytesIn, 0, received, 0, i);

    fifo.Enqueue(received);
}

我认为这里的主要问题是您对在 while-loop 之外声明的队列添加引用类型的误解。

如果仔细查看您提供的代码,您会发现您只声明了一次 bytesIn。您将 bytesIn 入队,然后 重写 数组的值。但是,该数组仍然是与以前相同的对象,因此不能再次排队,因此它将数组更改为新值。

那么我们真正想做的是什么?我们想要;

  • 阅读流
  • 将输出放入 new array-object
  • 入队新对象

这正是@dcastro 所做的,但我会为您精简代码;

while ((
         i = stream.Read(bytesIn, 0, bytesIn.Length)) != 0    //read the contents of the 
                                                              //stream and put it in 
                                                              //bytesIn, if available 
                                                            )
{
    var received = new byte[i];              //Create a new, empty array, which we are 
                                             //going to put in the queue.

    Array.Copy(bytesIn, 0, received, 0, i);  //Copy the contents of bytesIn into our new
                                             //array. This way we can reuse bytesIn while
                                             //maintaining the received data.

    fifo.Enqueue(received);                  //Enqueue the new array and thus saving it.
} 

有关更多信息,也许您应该阅读 Reference types