0

There are plenty of explanations of await and async, now available in C#; but nothing seems to explain why this...

using (XmlReader reader = XmlReader.Create(stream, settings))
{
    while (await reader.ReadAsync())
    {
        // Do something
    }
}

is better than this...

using (XmlReader reader = XmlReader.Create(stream, settings))
{
    while (reader.Read())
    {
        // Do something
    }
}

In other words, if you have no intention of doing other stuff while you await for the ...Async method to do its thing, why use it all? If a synchronous method is available, why not just use that?

This Async example is taken from: https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlreader?view=netframework-4.7.1

EDIT: Having read the question and answer to which this was thought to be a duplicate, they did not help. I was asking specifically about the simple case of having await on the same line as the Async method being called. My question has been answered below. Thank you all!

Peter D
  • 11
  • 1
  • If you're using any UI based platform, the synchronus method blocks the UI thread. (freeze the UI in case of WPF/Win forms). That may lead to OS flagging the program as Not Responding. Hence, using async method, the UI will be responsive – Skyuppercut Mar 08 '18 at 08:18
  • The async method call is async because it's waiting on IO, if you are working on Mobile or desktop, the synchronous thread blocks UI thread and on the server using asynchronous methods is a big win. The server can free up and reuse the current thread waiting for the async method call to complete, which uses a signal for notification. Asynchronous methods when the method is IO bound can dramatically increase scalability on a server. – Tornike Gomareli Mar 08 '18 at 10:42

4 Answers4

6

Fundamentally, using an asynchronous method call will not block the thread, which is a finite resource on any machine. Let's say you have a method call that might take 3 seconds to complete due to network latency, heavy database workload, etc. If you call this method synchronously, your thread is actually sitting there waiting for the results to come back, oblivious to the rest of your application.

Asynchronous method calls (or async/await, as it's colloquially known and called) are non-blocking. So if your executing thread encounters a method that indicates it can be awaited, it will (and I'm vastly oversimplifying things here) put a flag in the sand and tell the system to just do the thing and give me a call when you're done.

Now you're probably thinking, "But wait! Doesn't that mean another thread has to do the job the current thread just delegated?!" and you'd be correct.

This is where the concept of foreground and background threads comes in. An example of a foreground thread would be something like the thread handling a web API call in the controller, or a UI rendering thread.

Blocking these threads is detrimental for several reasons, in the case of API threads you're basically narrowing the window of how many requests per second you can handle at any given time. In the UI case, it might stall the rendering for several seconds while it's doing work in the background.

So what are the positives and negatives in general? You're distributing your thread workload more evenly when using async/await, at the detriment of memory overhead (something's going to have to remember where all the flags in the sand are, and keep track of when the process can continue).

When people say it's making the application more performant, this is true by making it more concurrent, but not necessarily faster.

To address the comment left by Mihir Dave:

Misuse of async/await would include trying to apply it to pure computational methods (eg. no I/O, purely CPU bound). At that point you're adding a lot of complexity and overhead for no benefit. Another bad application is not embracing it top to bottom, if you start trying to "syncify" async methods, or "asyncify" sync methods, the risk for deadlocks increases dramatically. The latter is quite common when working with outdated APIs, that may not expose async methods.

An extensive read about async/await read would be Q: why-shouldnt-all-functions-be-async-by-default

Yannick Meeus
  • 5,643
  • 1
  • 35
  • 34
  • Nice Answer. i had a question is it possible if someone missuses async/await they might end up.losing performance? – Mihir Dave Mar 08 '18 at 10:59
  • @MihirDave Answered in an edit to my answer as it turned out to a lengthier than allowed comment. – Yannick Meeus Mar 08 '18 at 11:44
  • 1
    You said "Now you're probably thinking, "But wait! Doesn't that mean another thread has to do the job the current thread just delegated?!" and you'd be correct.", but that is not always the case. In most I/O, the main work is handled by the devices. ALL cpu threads are free and available to do anything else needed. The device, when is complete, will send an interrupt signal to the cpu and only then the cpu will allocate one of the threads to execute the continuation code. Async trully frees your threads. – Thanasis Ioannidis Oct 15 '19 at 20:43
2

It will free up a thread to do other things (potentially) instead of spinning and waiting for the IO to complete. For web applications this helps the application scale by using these threads to handle more requests. For UI applications it allows the main (UI) thread to keep the application responsive to user input.

You can read more about the benefits of async in .NET here.

Alex Wiese
  • 8,142
  • 6
  • 42
  • 71
1

you wrote:

if you have no intention of doing other stuff while you await ...

Well maybe your procedure has no intention of doing other stuff while you await, but your caller might want to!

If you call await for a task, and the task is not completed yet, your thread goes up the call stack to see if your caller is awaiting your task, and if not, the thread starts executing statements until he has to await. The thread goes up the call stack again.

So even if you don't have to do something useful, if you think there might be the slightest chance that your caller might want to do something instead of waiting until you are ready, better make your function async whenever you have the choice to call async functions. If you think that your class will be used widely, consider creating an async and a non-async version

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
  • This answers my question. It also explains why when I use an await within a method, I need to change my own method signature to include the async modifier. I never really understood that either. Thank you. – Peter D Mar 08 '18 at 19:33
0

It depends on your use case. Using await will free up the current thread to do other things. If this thread is the UI thread in a desktop application, you must free it to process the UI. If you are on a webserver you will want to free up the thread to process other requests, threads are not free, they take up 1MB if memory for stack space.

If you are not concerned about any of those scenarios calling the sync version is ok as well

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357