none
async , await RRS feed

  • Question

  • Hello,
    I use await, because I muts wait until the message sent.
    UserInteface should not frozen.

    public async void SendRequest(Socket sck, string msg)
    await Task.Delay(0); Do you think, that is right. Need I here await.

    Is the spelling correct?

    Best regards, Markus

    internal async void SendSocket(Socket sck, string msg)
    {
    	try
    	{
    		Action actionSend = () =>
    		{
    			SendRequest(sck, msg);
    		};
    
    		await Task.Run(actionSend);   // besser so verwenden
    
    		//await Task.Run(() =>
    		//{
    		//    //receiveBuffer = "";
    		//    byte[] buf1 = Encoding.Default.GetBytes(msg);
    		//    if (sck != null && sck.Connected)
    		//        sck.Send(buf1);
    		//});
    	}
    	catch (Exception ex)
    	{
    		Log.Error($"SendSocket {ex.Message}");
    	}
    }
    
    public async void SendRequest(Socket sck, string msg)
    {
    	byte[] buf1 = Encoding.Default.GetBytes(msg);
    	if (sck != null && sck.Connected)
    		sck.Send(buf1);
    
    	await Task.Delay(0);
    }

    Friday, February 8, 2019 5:04 PM

Answers

  • If you're referring to just the name change you made from `SendRequestAsync` to `SendRequestSync` then it is literally just a name change. However we don't mark synchronous methods with any suffix, just async methods and it is always `Async`. In fact if you're using VS 2017+ and have an .editorconfig file or have configured your styling rules then one of them is that Task-returning methods end with `Async`. This is so that callers know the behavior. Take an example.

    class MyType
    {
       Task Foo () { return Task.CompletedTask; }
    }
    
    var data = new MyType();
    
    data.Foo();

    This code looks correct but it is wrong. Foo returns a Task. Calling code needs to know this because if they don't wait for the result (using Result, Wait or await) then there is a fundamental logic flaw in there. If you never wait on a task then any errors it throws will be silently ignored which can cause problems. So you want a caller to know that a method returns a Task. Simply relying on them looking at the signature is not sufficient because, as you can see in the above code, it isn't obvious. By naming the method with `Async` it becomes clear looking at the above code that there should be a wait somewhere.

    In the SendRequestAsync method I posted it was just an async version of the sync SendRequest method. Since SendRequest didn't really gain anything by being async it remained unchanged but if I wanted to call it from an async method writing that extra code seems redundant. The SendRequestAsync method is just a boilerplate method to convert a sync method to async. If you never need it then you can leave it out.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by Markus Freitag Sunday, February 10, 2019 11:28 AM
    Saturday, February 9, 2019 4:03 PM
    Moderator

All replies

  • Async methods should return Task, not void. Your SendRequest method isn't actually async. When you call Send it'll block the caller until the send completes. If this happens to be called on the UI thread then the UI thread stalls.

    //Notice the name change to make this clear...
    internal async Task SendSocketAsync ( Socket sck, string msg )
    {
       try  
       {
          await Task.Run(() => SendRequest(sck, msg);
       } catch (Exception ex)
       {
          Log.Error($"SendSocket {ex.Message}");
       };
    }
    
    //Not async, doesn't need to be
    public void SendRequest ( Socket sck, string msg )
    {
       var buf1 = Encoding.Default.GetBytes(msg);
       if (sck != null && sck.Connected)
          sck.Send(buf1);
    }
    
    //If you want SendRequest to support async then change up the code
    public Task SendRequestAsync ( Socket sck, string msg )
    {
       return Task.Run(() => SendRequest(sck, msg));
    }

    In whatever UI handler you are ultimately going to call this stuff against just use the SendSocket version.

    private async void SomeUIEventHandler ( object sender, EventArgs e )
    {
       //Everything up to here runs on the UI thread, then 
       //control returns to the UI until the task completes
       await SendSocketAsync(mySocket, "Hello");
    
       //Still on UI thread
    }


    Michael Taylor http://www.michaeltaylorp3.net

    • Proposed as answer by Cherkaoui.Mouad Saturday, February 9, 2019 9:38 AM
    • Marked as answer by Markus Freitag Saturday, February 9, 2019 11:42 AM
    • Unmarked as answer by Markus Freitag Saturday, February 9, 2019 11:57 AM
    Friday, February 8, 2019 6:18 PM
    Moderator
  • Sorry, one more question. I want to be sure to understand it.

    // async clear!

    internal async Task SendSocketAsync ( Socket sck, string msg ) { try { await Task.Run(() => SendRequest(sck, msg); } catch (Exception ex) { Log.Error($"SendSocket {ex.Message}"); }; } //sync    clear! no await public void SendRequest ( Socket sck, string msg ) { var buf1 = Encoding.Default.GetBytes(msg); if (sck != null && sck.Connected) sck.Send(buf1); } // sync    but with task! public Task SendRequestSync ( Socket sck, string msg ) { return Task.Run(() => SendRequest(sck, msg)); }

    // What is now here different -- is sync or? Is not waiting

    // for response

    Greeting Markus



    Saturday, February 9, 2019 12:01 PM
  • If you're referring to just the name change you made from `SendRequestAsync` to `SendRequestSync` then it is literally just a name change. However we don't mark synchronous methods with any suffix, just async methods and it is always `Async`. In fact if you're using VS 2017+ and have an .editorconfig file or have configured your styling rules then one of them is that Task-returning methods end with `Async`. This is so that callers know the behavior. Take an example.

    class MyType
    {
       Task Foo () { return Task.CompletedTask; }
    }
    
    var data = new MyType();
    
    data.Foo();

    This code looks correct but it is wrong. Foo returns a Task. Calling code needs to know this because if they don't wait for the result (using Result, Wait or await) then there is a fundamental logic flaw in there. If you never wait on a task then any errors it throws will be silently ignored which can cause problems. So you want a caller to know that a method returns a Task. Simply relying on them looking at the signature is not sufficient because, as you can see in the above code, it isn't obvious. By naming the method with `Async` it becomes clear looking at the above code that there should be a wait somewhere.

    In the SendRequestAsync method I posted it was just an async version of the sync SendRequest method. Since SendRequest didn't really gain anything by being async it remained unchanged but if I wanted to call it from an async method writing that extra code seems redundant. The SendRequestAsync method is just a boilerplate method to convert a sync method to async. If you never need it then you can leave it out.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by Markus Freitag Sunday, February 10, 2019 11:28 AM
    Saturday, February 9, 2019 4:03 PM
    Moderator