I'd like to find out if there is any way I could somehow fire an event when my UdpClient receives data? (System.Net.Sockets.UdpClient)
I tried overriding it's UdpClient.Receive but I can't according to this because overridable members have to be marked virtual or abstract.
The way I am currently doing it is by running a TimerCallback on Threading.Timer at specific intervals to fetch my data but I'd prefer to receive incoming data as it arrives instead of fetching it repeatedly.
Any suggestions, recommendations or pointers as to how I can do this or do I HAVE TO manually receive on intervals?
Overriding the Receive
method wouldn't help you anyway - it's not a method that's called when the UDP client receives data, it's a method you call when you want to wait for incomming data.
However, the Receive
method blocks. This means that you don't really have to check at intervals - you can simply check in an (almost) infinite loop. Just do it in a different thread.
void Loop(CancellationToken token)
{
var remoteEP = default(IPEndPoint);
while (!token.IsCancellationRequested)
{
var data = client.Receive(ref remoteEP);
yourForm.Invoke(DataReceived, data);
}
}
And of course, since this is simple I/O, there's no need to occupy a thread to do this - you can use asynchronous I/O:
public Task Loop(CancellationToken token)
{
using (UdpClient client = new UdpClient(80))
{
while (!token.IsCancellationRequested)
{
var data = await client.ReceiveAsync();
// Process the data as needed
}
}
}
In a winforms or WPF application, this will work pretty much automagically - you'll just use this code in say btnStart_Click
event handler, and it will keep your UI responsive while waiting for data in the background; and whenever the data gets back, it will execute the rest of the code (Process the data as needed
) on the UI thread - no need to create any threads manually or handle dispatching.
Of course, it's somewhat tricky to handle termination, but that's always tricky with UDP - basically, you'd either have to use the more manual way that supports cancellation (ReceiveAsync
is just a wrapper for BeginReceive
and EndReceive
which don't support cancellation), or you'd use the old trick of setting the cancellation token and then sending a 0-length data packet to yourself (causing the Receive
call to end and return a zero-length byte array).
You can also use Rx Extensions to receive the data.
Wrap the ReceiveAsync
from the UpdClient
in an Observable.FromAsync
and subscribe to the observable.
UdpClient client = new UdpClient(..., ...);
var obs = Observable.FromAsync(client.ReceiveAsync);
var sub = obs.Subscribe(...);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With