Stuyvenstein
Stuyvenstein

Reputation: 2447

C#.Net UdpClient Receive Event

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?

Upvotes: 4

Views: 9468

Answers (3)

jpmnteiro
jpmnteiro

Reputation: 777

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(...);

Upvotes: 3

Luaan
Luaan

Reputation: 63732

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).

Upvotes: 6

Vincent
Vincent

Reputation: 21

UdpClient.Receive blocks the execution until it receives data from the endpoint. But there is an asyncronous alternative, UdpClient.BeginReceive. It's not exactly an event, but works in a similar way and you can encapsulate it and fire your own events. The documentation (with code example) can be found here: http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.beginreceive(v=vs.110).aspx

Upvotes: 2

Related Questions