I have some code that used to work for many years and even now in specific cases it works but in other cases I just cannot understand why it fails.
The following code is part of a Client class that uses a System.Net.Sockets.Socket
for communication:
protected ConcurrentQueue<byte[]> ReadQueue { get; } = new ConcurrentQueue<byte[]>();
private void ReadTimer_Tick(object sender, EventArgs e) {
ReadTimer.Stop();
try
{
while (ReadQueue.Count > 0 && !IsDisposing)
{
try
{
if (this.ReadQueue.TryDequeue(out var data))
{
[...]
}
}
catch (Exception ex)
{
[...]
}
}
}
catch (Exception)
{
[...]
}
finally
{
if (IsConnected && !IsDisposing) ReadTimer.Start();
}
}
protected void EnqueueData(IEnumerable<byte> data)
{
ReadQueue.Enqueue(data.ToArray());
}
The ReadTimer
ticks every millisecond if it is not stopped in order to process data from the ConcurrentQueue
.
There are two uses of the code:
First case
I open a connection to a Socket
port. After the connection is established I call the Socket.BeginReceive
method of the Socket
.
Second case
I listen to a Socket
port and call the Socket.BeginAccept
method. Within the ´callback´ method of BeginAccept
I also call the BeginReceive
method of the Socket
.
In both cases the same method is called:
private void StartReceiving(SocketAnswerBuffer state)
{
try
{
Status = ClientStatus.Receiving;
_ = state.Socket.BeginReceive(
state.Buffer, 0,
state.Buffer.Length,
SocketFlags.None,
ReceiveCallback,
state
);
}
catch (Exception ex)
{
[...]
}
}
So in both cases the ReceiveCallback
is used to handle incoming data:
private void OnReceive(IAsyncResult result)
{
if (result.AsyncState is SocketAnswerBuffer state)
{
try
{
var size = state.Socket.EndReceive(result);
if (size > 0)
{
var data = state.Buffer.Take(size).ToArray();
EnqueueData(data);
}
}
catch (Exception ex)
{
[...]
}
finally
{
Status = ClientStatus.Connected;
if (state != null && state.Socket.Connected)
StartReceiving(state);
}
}
}
In both cases the EnqueueData
method is called.
In the first case everything works. When the ReadTimer
ticks ReadQueue.Count
is more than 0 and the loop handles all data collected so far and processes it.
In the second case EnqueueData
is also called and enqueues data to the ReadQueue
. But when the ReadTimer
ticks ReadQueue.Count
is 0 and nothing works.
What I really cannot understand is that debugging the code shows that ReadQueue.Count
is larger than 0 on EnqueueData
and the ReadQueue
even grows but in ReadTimer_Tick
the ReadQueue
remains empty ... I neither clear nor redeclare ReadQueue
and ReadTimer_Tick
is the only method in code that tries to dequeue the data from ReadQueue
.