What happens to incoming messages during a UDPClient asynchronous callback?
So we have about 30 UDP messages coming in per second, and on each message we are performing processing and database operations. My first thought is to complete the operations, then call the BeginReceive method again and let the next message come in. Since there is a slight interim between when the message is received and when BeginReceive is called again, what happens to messages that are received in this interim? Also, if I move the BeginReceive to the beginning of the asynchronous callback before the operations, would this create all kinds of thread complications or even be possible to do safely?
Public Sub Start() _udpclient.BeginReceive(New AsyncCallback(AddressOf ReceiveCallback), Nothing) End Sub
Public Sub ReceiveCallback(ar As IAsyncResult) Try Dim bytes As Byte() = _udpclient.EndReceive(ar, _ipendpoint) HeavyProcessAndDBOperation(bytes) _udpclient.BeginReceive(New AsyncCallback(AddressOf ReceiveCallback), Nothing) Catch ex1 As Exception End Try End Sub
Public Sub ReceiveCallback(ar As IAsyncResult) Try Dim bytes As Byte() = _udpclient.EndReceive(ar, _ipendpoint) _udpclient.BeginReceive(New AsyncCallback(AddressOf ReceiveCallback), Nothing) HeavyProcessAndDBOperation(bytes) Catch ex1 As Exception End Try End Sub
You want that client receiving data again as immediately as possible after a packet is received.
If I remember correctly, each call to ReceiveCallback will be fired in a separate thread, so calling BeginReceive in your callback right away (as per your method 2) is the pattern you want here.
You'll have one thread per ReceiveCallback that gets fired, that is: per packet, essentially. Each ReceiveCallback will fire one more thread to BeginReceive immediately, which will allow you to receive as much data as you can.
As for packets in the interim: keep in mind that UDP is a connection-less protocol. By using your method 2, you will minimize but potentially not eliminate packet-loss. It is possible that you miss packets between EndReceive and BeginReceive.
If you opt for method 1, you will lose the number of packets sent in the time window occupied by HeavyProcessAndDBOperation().
The ReceiveCallback threads are independent of each other and data processed in one will not be affected by data processed in the others Unless it is a shared field, database connection, etc....
What you may want to do here to remedy the shared fields etc.., and I don't know the best solution so take this with a grain of salt, is: fire another thread in each ReceiveCallback into HeavyProcessAndDBOperation. From within that thread, put a lock around your actual database operations and shared-field processing. This will increase the time required to process the data, but since it's in another thread it will not affect the receive operation of other packets.
I'm not sure the correct method for locking a processing block. I used to use SyncLock, but it's been a few years since I've done this sort of work so you may want to do a bit of research there.
Hope that helps.