I want to create Socket message sending via TAP via async/await.
After reading this answer and this one - I decided to create a fully working sample :
So what ha
the problem comes from the "notice I removed the async from main since im testing it in console.".
You need to wait for the operation to complete before doing the next step. The code you used as an example pauses at each await
for the operation to complete, your code just goes straight through.
You may be able to fix this by putting a .Wait()
after each operation that would have had a await
or by running this function inside a threadpool thread via Task.Run(
, however I think it is better to know when you should use async and when you should not.
Async should be used when you have other work you could have the thread be doing, very commonly that "other work" will be things like processing UI messages on a WinForms project or accepting new connections on a ASP.NET site. In a console application there is no other work your program could be doing while it waits, so in that situation it would be more appropriate to use the synchronous version of the functions instead.
P.S. You made the comment after I posted "that's why I remove the async awaits and used Task.result", just so you know never ever1 combine code that uses await
and code that blocks the synchronization contest (by using things like Task.Result
or Task.Wait()
, you will likely cause your code to deadlock and stop functioning!
It is not a issue for your current example because console applications do not have a synchronization context, but if you copied and pasted this code to something that did you could easily lock up your program.
1: Ok, you could combine await
and blocking code but there are rules you need to follow, but if you know enough to dispute my what I am saying you know enough to safely do it. If you don't know how to safely do it just avoid doing it
since you do not wait for the threads to do their work and then call s.Close()
the socket will be closed before any traffic is sent out.
You would have to either remove the s.Close()
call or wait until the calls are complete, for instance via
Task connect = s.ConnectTaskAsync( "127.0.0.1" , 443);
connect.Wait(); // you have to connect before trying to send
Task sendData = s.SendTaskAsync(Encoding.UTF8.GetBytes("hello"));
sendData.Wait(); // wait for the data to be sent before calling s.Close()
s.Close();
or you could box it in a method and Wait for that method to complete. The end result is to not call Close
before completing the previous calls.
void Main()
{
Socket s = new Socket(SocketType.Stream , ProtocolType.Tcp);
Task worker = DoWorkAsync(s);
worker.Wait();
s.Close();
Console.ReadLine();
}
private async Task DoWorkAsync(Socket s){
await s.ConnectTaskAsync( "127.0.0.1" , 443);
await s.SendTaskAsync(Encoding.UTF8.GetBytes("hello"));
}