你好stackoverflow!我会切入追逐: 我有一个使用TCP的服务器/客户端程序,我在用于将读取数据包放入的队列中遇到一些问题。一旦读取数据包就会将其排入队列,如果程序没有忙于处理它将处理它并将其从队列中出列。
以下是排队数据的代码:
If ReadIndex = ReadBuffer.Length Then
SyncLock ReadQueue
ReadQueue.Enqueue(ReadBuffer)
End SyncLock
File.WriteAllBytes(Application.StartupPath & "\Test\" & I & ".bin", ReadBuffer)
I += 1
If Not Processing(2) Then
Processing(2) = True
If Not ThreadPool.QueueUserWorkItem(AddressOf HandleReadQueue) Then HandleReadQueue()
End If
End If
请注意,我正在将所有数据包写入每个自己的文件(这是出于调试目的)。我使用ThreadPool来处理不同线程上的读数。
以下是处理队列的方法:
Private Sub HandleReadQueue()
Dim Data As Byte()
SyncLock ReadQueue
Data = ReadQueue.Dequeue()
End SyncLock
File.WriteAllBytes(Application.StartupPath & "\TestReadQueue\" & Y & ".bin", Data)
Y += 1
If _Parent IsNot Nothing Then
HandleClientReadPacket(_Parent, _Pipename, Data)
Else
HandleClientReadPacket(Me, Nothing, Data)
End If
End Sub
TestReadQueue中的文件与Test文件夹中的文件不同。我不知道为什么。而且我知道所有数据都是收到的,因为入队的数据与客户端发送的数据相同。
在这里你可以看到它的不同之处: http://gyazo.com/feb4a192e47f262a9f23812ae8bc6cf6
当我使用ThreadPool时不会出现此问题,但是当我不使用SyncLock时没有必要..有谁能告诉我什么是错的?
答案 0 :(得分:2)
ReadBuffer在入队后确实被修改了,但我认为入队是按值而不是引用?
引用按值排列。
数组总是引用类型。最后在队列中的所有内容都是对字节数组的引用。例如(C#)
var queue = new Queue<byte[]>();
byte[] buffer = { 1 };
queue.Enqueue(buffer);
buffer[0] = 100;
var dequeued = queue.Dequeue();
Console.WriteLine(dequeued[0]); // 100
如果您希望排队的引用独立于您将要覆盖的字节数组,则需要克隆它。例如,在C#中你可以使用:
queue.Enqueue((byte[]) buffer.Clone());
使用您在VB中最合适的视图 - 但重要的是该数组是克隆的,因此独立于您仍在修改的原始数组。