How to use asynchronous Receive for UdpClient in a loop?

Corey Burnett picture Corey Burnett · Feb 13, 2013 · Viewed 14.6k times · Source

I am building a multi-threaded application. One of the threads is responsible for processing UDP messages that come from an external piece of hardware. I am currently using the UdpClient.Receive method in a loop. I believe that the Receive method blocks the thread while waiting for the next message. I have a shared variable (_isCancelled) that I use if I want to shut down all of the threads and gracefully stop the application. However because this Receive method blocks I can't gracefully shut down the application if communication has been lost to the external piece of hardware. Here is the current code loop

UdpClient _client = new UdpClient(8000);
IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, 8000);
while (!_isCancelled)
{
  byte[] _bytes = _client.Receive(ref _endPoint);
  ...process data...
}

I am thinking that I should instead use the asynchronous Receive methods. But I am not completely sure I understand how those work and how I should structure my code. I want to be able to continuouslly receive data and process it. And at any time I want to be able to gracefully shut down the thread by setting _isCancelled to true. And if for some reason we lose communication to the external hardware or don't receive any more messages, we should still be able to gracefully shut down the thread.

Answer

Mehrad picture Mehrad · Jun 11, 2014

For newer methods using TAP instead of Begin/End method you can use the following in .Net 4.5

Quite simple!

Asynchronous Method

    private static void UDPListener()
    {
        Task.Run(async () =>
        {
            using (var udpClient = new UdpClient(11000))
            {
                string loggingEvent = "";
                while (true)
                {
                    //IPEndPoint object will allow us to read datagrams sent from any source.
                    var receivedResults = await udpClient.ReceiveAsync();
                    loggingEvent += Encoding.ASCII.GetString(receivedResults.Buffer);
                }
            }
        });
    }

Synchronous Method

As appose to the asynchronous method above, this can be also implemented in synchronous method in a very similar fashion:

    private static void UDPListener()
    {
        Task.Run(() =>
        {
            using (var udpClient = new UdpClient(11000))
            {
                string loggingEvent = "";
                while (true)
                {
                    //IPEndPoint object will allow us to read datagrams sent from any source.
                    var remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                    var receivedResults = udpClient.Receive(ref remoteEndPoint);
                    loggingEvent += Encoding.ASCII.GetString(receivedResults);
                }
            }
        });
    }