Все элементы в 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.
}
Для получения дополнительной информации, возможно, вам следует прочитать о ссылочных типах.