Reputation: 9445
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
METHOD 1:
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
METHOD 2:
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
Upvotes: 0
Views: 419
Reputation: 4593
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.
Upvotes: 1