How do I receive messages asynchronously?

57 Views Asked by At

How do I change the code to receive messages asynchronously? The application is written in C# WinForms

My application sends messages asynchronously, does not receive synchronously. What should I change so that it receives asynchronously? `

  private void ReceiveUDPMessage()
   {
       while (true)
       {
           try
           {
               Int32 port = Int32.Parse(LocalPortTextBox.Text);
               IPAddress ip = IPAddress.Parse(LocalIPTextBox.Text.Trim());
               IPEndPoint remoteIPEndPoint = new IPEndPoint(ip, port);
               byte[] content = udpClient.Receive(ref remoteIPEndPoint);
               if (content.Length > 0)
               {
                   string message = Encoding.ASCII.GetString(content);

                   // Обработка полученных сообщений и обновление состояния робота
                   HandleReceivedMessage(message);
               }
           }
           catch
           {
               string errmessage = "RemoteHost lost";
               this.Invoke(myDelegate, new object[] { errmessage });
           }
       }
   }

   private void HandleReceivedMessage(string message)
   {
       switch (message)
       {
           case "MoveToSector1":
               UpdateRobotState(RobotState.MovingToSector1);
               break;
       }
   }`
1

There are 1 best solutions below

0
Harald Coppoolse On BEST ANSWER

If you want to make a method for async-await, you'll have to do the following:

  • Declare it async
  • Change the return type. Return Task instead of void; return Task<TResult> instead of TResult. The only exception to this are event handlers. They return void, even though they are declared async.
  • Inside your method use all async methods that are available. So if you are querying from a database, fetching data from the internet and writing result to a disk, use all three async methods.
  • Before returning, make sure you have awaited all async calls.
  • The return value of await Task<TResult> is TResult.

It is custom to add Async to the name of the method. This way you can have both a sync and an async method: File.Write and File.WriteAsync

Until now, you were using

public byte[] Receive (ref System.Net.IPEndPoint? remoteEP);

However the async method, doesn't have a parameter that contains the IpEndPoint

public Task<System.Net.Sockets.UdpReceiveResult> ReceiveAsync ();

The Received data and the RemoteEndPoint are in the UpdReceiveResult. So after await you'll have to fetch them.

private async Task ReceiveUDPMessageAsync()
{
    while (true)
    {
        try
        {
            // do some preparations before you call the async method
            Int32 port = Int32.Parse(LocalPortTextBox.Text);
            IPAddress ip = IPAddress.Parse(LocalIPTextBox.Text.Trim());
            IPEndPoint remoteIPEndPoint = new IPEndPoint(ip, port);
           udpClient.Connect(ipEndPoint);

            // call the async method.
            // To show what happens I write it with intermediate steps
            Task<UdpReceiveResult> taskReceive = udpClient.ReceiveAsync();

            // Because I didn't await yet, if needed I could do something else
            // while the udpClient is receiving, for example:
            DoSomethingElse();

            // Now you can't continue without the result of the async Receive
            // action,await for it:
            UdpReceiveResult receiveResult = await taskReceive;

            remoteIPEndPoint = receiveResult.RemoteEndPoint;
            byte[] content = receiveResult.Buffer;

            if (content.Length > 0)
            {
                string message = Encoding.ASCII.GetString(content);

                // Обработка полученных сообщений и обновление состояния робота
                HandleReceivedMessage(message);
            }
        }
        catch
        {
            string errmessage = "RemoteHost lost";
            this.Invoke(myDelegate, new object[] { errmessage });
        }
    }
}

Of course, if you've got nothing to do but await, you can combine these statements:

UdpReceiveResult receiveResult = await udpClient.ReceiveAsync();
byte[] content = receiveResult.Buffer;
etc.