How to use asynchronous Receive for UdpClient in a loop?

无人久伴 提交于 2019-12-01 10:47:41

问题


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.


回答1:


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);
                }
            }
        });
    }



回答2:


I've added some code to demonstrate how you could implement the loop by using BeginReceive/EndReceive. This shows you a stripped down version you could easily modify or implement:

UdpClient local;
bool stop;

public void StartReceiving() 
{
    local = new UdpClient(serverIP);
    Receive(); // initial start of our "loop"
}

public void StopReceiving() 
{
    stop = true;
    local.Client.Close();
}

private void Receive() 
{   
    local.BeginReceive(new AsyncCallback(MyReceiveCallback), null);
}

private void MyReceiveCallback(IAsyncResult result) 
{
    IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0);
    local.EndReceive(result, ref ip);

    if (!stop)
    {
        Receive(); // <-- this will be our loop
    }
}

Have fun




回答3:


Another approach with some support for cancelling. I prefer the recursive feel to the while(true) loop.

private async void Listen()
{
    var resp = await _udpClient.ReceiveAsync().ConfigureAwait(false);

    var eventHandler = PacketReceived;
    if (eventHandler != null)
        eventHandler(this, new UdpPacketReceivedEventArgs(resp));

    if (_running)
        Listen();
}


来源:https://stackoverflow.com/questions/14860613/how-to-use-asynchronous-receive-for-udpclient-in-a-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!