Hello there stackoverflow! I'll just cut to the chase: I have a server / client program using TCP and I am having some trouble with the queue I use to put read packets in. This works by once a packet is read it's enqueued into the queue, and if the program isn't busy handling the packet it will handle it and dequeue it from the queue.
Here is the code for enqueuing the data:
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
Note that I am writing all the packets to each own file (this is for debugging purposes). I use the ThreadPool to handle the readqueue on a different thread.
And here is the method for handling the queue:
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
The files in TestReadQueue is different from the ones in the Test folder. I have no idea why. And I know for a fact that all the data is received as the data that is enqueued is identical to the one the client sends.
Here you can see it's different: http://gyazo.com/feb4a192e47f262a9f23812ae8bc6cf6
This problem does not occure when I use ThreadPool, but then when I dont use that SyncLock isn't necessary.. Can anyone tell me what's wrong?
The ReadBuffer is indeed modified right after its enqueued, but I thought enqueuing is by value and not reference?
The reference is enqueued by value.
Arrays are always reference types. All that ends up in the queue is a reference to the byte array. For example (C#)
var queue = new Queue<byte[]>();
byte[] buffer = { 1 };
queue.Enqueue(buffer);
buffer[0] = 100;
var dequeued = queue.Dequeue();
Console.WriteLine(dequeued[0]); // 100
If you want the reference that is queued to be independent of the byte array that you're going to be overwriting, you need to clone it. In C# for example you could use:
queue.Enqueue((byte[]) buffer.Clone());
Use whichever casting you view as most appropriate in VB - but the important part is that the array is cloned, and therefore independent of the original array that you're still modifying.