I have developed a C# program that receives UDP packets and writes the received data to a queue on thread A. The program reads from the queue, performs some data processing, and then sends another UDP packet with the modified data on thread B. Here is a simplified portion of my code:
public void Task ListeningThread()
{
while (true)
{
int bytesReceived = mySocket.ReceiveFrom(buffer, ref RemoteEP);
logfile.WriteLine("dtReceived: " + (DateTimeOffset.Now - previousreceiveTime).ToString(@"ss\.ffff"));
previousreceiveTime = DateTimeOffset.Now;
if (bytesReceived > 0)
{
byte[] receivedPacket = new byte[bytesReceived];
Array.Copy(buffer, receivedPacket, bytesReceived);
packetQueue.Add(receivedPacket);
}
}
}
public void Task ProcessingThread()
{
byte[] array = Enumerable.Repeat((byte)0x20, 500).ToArray(); //For testing
while (true)
{
foreach (var packet in packetQueue.GetConsumingEnumerable())
{
Socket.SendTo(array, SocketFlags.None, new IPEndPoint(IPAddress.Parse("172.16.108.162"), 565));
dttw.WriteLine("dtSent: " + (DateTimeOffset.Now - previousreceiveTime).ToString(@"ss\.ffff") + " Data: " + array.data);
}
}
}
I am receiving UDP packets at 100 Hz, so when things are working correctly the logfile and associated wireshark capture look something like this:
dtReceived: 00.0100
dtSent: 00.0007 Data: 124
dtReceived: 00.0100
dtSent: 00.0009 Data: 125
dtReceived: 00.0099
dtSent: 00.0007 Data: 126
dtReceived: 00.0099
dtSent: 00.0009 Data: 127
dtReceived: 00.0100
dtSent: 00.0011 Data: 128
(.161 is my local machine, .163 is the machine that I am receiving data from, and .162 is the machine that I am sending data to.)
However, occasionally the following behavior occurs:
dtReceived: 00.0100
dtSent: 00.0006 Data: 82
dtReceived: 00.0099
dtSent: 00.0006 Data: 83
dtReceived: 00.0607 //<-- Problem here, data should have been received after 0.0100 seconds
dtReceived: 00.0000 //<-- 5 more messages have stacked up in the mean-time
dtReceived: 00.0000
dtReceived: 00.0000
dtReceived: 00.0000
dtReceived: 00.0000
dtSent: 00.0007 Data: 84 //<-- After the 6 packets arrive near-simultaneously, 6 packets are sent in quick succession
dtSent: 00.0026 Data: 85
dtSent: 00.0037 Data: 86
dtSent: 00.0047 Data: 87
dtSent: 00.0056 Data: 88
dtSent: 00.0064 Data: 89
dtReceived: 00.0091
dtSent: 00.0007 Data: 90
dtReceived: 00.0100
dtSent: 00.0006 Data: 91
The Wireshark capture indicates that the incoming are arrive at the correct rate. However, the packets are stacking up before finally arriving at the application, at which time all of the incoming packets are received and processed nearly simultaneously. This is running on a Windows 11 system. Neither the CPU nor the network adapter is anywhere close to being taxed. Does anyone have an idea of what could be causing this or a potential solution?
I have developed a C# program that receives UDP packets and writes the received data to a queue on thread A. The program reads from the queue, performs some data processing, and then sends another UDP packet with the modified data on thread B. Here is a simplified portion of my code:
public void Task ListeningThread()
{
while (true)
{
int bytesReceived = mySocket.ReceiveFrom(buffer, ref RemoteEP);
logfile.WriteLine("dtReceived: " + (DateTimeOffset.Now - previousreceiveTime).ToString(@"ss\.ffff"));
previousreceiveTime = DateTimeOffset.Now;
if (bytesReceived > 0)
{
byte[] receivedPacket = new byte[bytesReceived];
Array.Copy(buffer, receivedPacket, bytesReceived);
packetQueue.Add(receivedPacket);
}
}
}
public void Task ProcessingThread()
{
byte[] array = Enumerable.Repeat((byte)0x20, 500).ToArray(); //For testing
while (true)
{
foreach (var packet in packetQueue.GetConsumingEnumerable())
{
Socket.SendTo(array, SocketFlags.None, new IPEndPoint(IPAddress.Parse("172.16.108.162"), 565));
dttw.WriteLine("dtSent: " + (DateTimeOffset.Now - previousreceiveTime).ToString(@"ss\.ffff") + " Data: " + array.data);
}
}
}
I am receiving UDP packets at 100 Hz, so when things are working correctly the logfile and associated wireshark capture look something like this:
dtReceived: 00.0100
dtSent: 00.0007 Data: 124
dtReceived: 00.0100
dtSent: 00.0009 Data: 125
dtReceived: 00.0099
dtSent: 00.0007 Data: 126
dtReceived: 00.0099
dtSent: 00.0009 Data: 127
dtReceived: 00.0100
dtSent: 00.0011 Data: 128
(.161 is my local machine, .163 is the machine that I am receiving data from, and .162 is the machine that I am sending data to.)
However, occasionally the following behavior occurs:
dtReceived: 00.0100
dtSent: 00.0006 Data: 82
dtReceived: 00.0099
dtSent: 00.0006 Data: 83
dtReceived: 00.0607 //<-- Problem here, data should have been received after 0.0100 seconds
dtReceived: 00.0000 //<-- 5 more messages have stacked up in the mean-time
dtReceived: 00.0000
dtReceived: 00.0000
dtReceived: 00.0000
dtReceived: 00.0000
dtSent: 00.0007 Data: 84 //<-- After the 6 packets arrive near-simultaneously, 6 packets are sent in quick succession
dtSent: 00.0026 Data: 85
dtSent: 00.0037 Data: 86
dtSent: 00.0047 Data: 87
dtSent: 00.0056 Data: 88
dtSent: 00.0064 Data: 89
dtReceived: 00.0091
dtSent: 00.0007 Data: 90
dtReceived: 00.0100
dtSent: 00.0006 Data: 91
The Wireshark capture indicates that the incoming are arrive at the correct rate. However, the packets are stacking up before finally arriving at the application, at which time all of the incoming packets are received and processed nearly simultaneously. This is running on a Windows 11 system. Neither the CPU nor the network adapter is anywhere close to being taxed. Does anyone have an idea of what could be causing this or a potential solution?
Share Improve this question edited Mar 19 at 21:19 Jake asked Mar 4 at 21:57 JakeJake 7910 bronze badges 8 | Show 3 more comments1 Answer
Reset to default 0I believe the problem here is related to the Windows CPU scheduling on the laptop that I am running this code on, as @Tangentially Perpendicular suggested. This is a "corporately managed" laptop with good hardware (13th gen i9 processor, 64 Gb RAM) but a lot of control software running in the background. This exact code ran on an unmanaged, offline laptop without any of the issues described above.
else { Thread.Sleep(1);
why is this here, why are you going to sleep if you need to wait for more packets? Why are you (clearly) using aConcurrentQueue
and not either aBlockingCollection.GetConsumingEnumerable
or aPipeReader
/PipeWriter
pair like learn.microsoft/en-us/dotnet/standard/io/pipelines which would be a much better fit. You should also be usingasync
to better handle async IO flows. – Charlieface Commented Mar 5 at 0:46Thread.Sleep
or any other such delaying mechanism. What doesapi.SendModifiedData
do, please show. – Charlieface Commented Mar 5 at 20:02