Все элементы в ConcurrentQueue<byte []> идентичны

У меня есть NetworkStream, который я использую для получения данных из другой программы. Данные поступают в виде байта [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 значения, а не указатели (если это правильная терминология)?

2 ответа

Решение

Вместо этого поставьте в очередь копию массива. Вы можете использовать ToArray расширение для этого.

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

Я также использовал Take обрезать буфер и копировать только те байты, которые были получены.

В качестве альтернативы, как предложено @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, а затем переписать значение массива. Массив, тем не менее, остается тем же объектом, что и раньше, и поэтому не может быть снова поставлен в очередь, поэтому он меняет массив на новое значение.

Так что же мы на самом деле хотим сделать? Мы хотим;

  • Читать поток
  • Поместите вывод в новый массив-объект
  • Поставьте в очередь новый объект

Именно это и делает @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.
} 

Для получения дополнительной информации, возможно, вам следует прочитать о ссылочных типах.

Другие вопросы по тегам