Async / await vs BeginRead, EndRead

I am not quite a 'get' async and am still waiting and I am looking for some clarification around the specific problem that I am going to solve. Basically, I need to write code that will handle the TCP connection. Essentially, it simply receives the data and processes it until the connection is closed.

I usually write this code using the NetworkStream BeginRead and EndRead patterns, but since the async / await pattern is much cleaner, I am tempted to use it. However, since I admittedly do not quite understand what is involved in them, I am a little afraid of the consequences. Will use more resources than another; whether a stream will be used in which another will use IOCP, etc.

Time for a minimized example. These two do the same - count the bytes in the stream:

class StreamCount { private Stream str; private int total = 0; private byte[] buffer = new byte[1000]; public Task<int> CountBytes(Stream str) { this.str = str; var tcs = new TaskCompletionSource<int>(); Action onComplete = () => tcs.SetResult(total); str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, onComplete); return tcs.Task; } private void BeginReadCallback(IAsyncResult ar) { var bytesRead = str.EndRead(ar); if (bytesRead == 0) { ((Action)ar.AsyncState)(); } else { total += bytesRead; str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, ar.AsyncState); } } } 

... and ...

  public static async Task<int> CountBytes(Stream str) { var buffer = new byte[1000]; var total = 0; while (true) { int bytesRead = await str.ReadAsync(buffer, 0, 1000); if (bytesRead == 0) { break; } total += bytesRead; } return total; } 

In my opinion, the asynchronous method looks cleaner, but there is a โ€œwhile (true)โ€ loop that my uneducated brain tells me that it will use an extra thread, more resources and therefore will not scale, as well as another. But I'm sure this is wrong. Do they do the same thing?

+6
source share
1 answer

In my opinion, the asynchronous method looks cleaner, but there is a โ€œwhile (true)โ€ loop that my uneducated brain tells me that it will use an extra thread, more resources and therefore will not scale, as well as another.

No, it will not. The loop will only use the thread when it actually runs the code ... just like in your BeginRead . The await expression returns control to the entire calling code by registering a continuation that returns to the right place in the method (in the appropriate thread based on the synchronization context), and then continues to work until it reaches the end of the method or falls into another await expression . This is exactly what you want :)

You should learn more about how async / await works behind the scenes - you can start with the MSDN page on it as a transition point.

+7
source

Source: https://habr.com/ru/post/977469/


All Articles