0

I was reading a chapter about the await and async keywords in my C# book. It was mainly explaining these kinds of method calls, where the caller uses the await keyword to wait for the called method to finish.

In this simple example I see no advantage but more importantly no difference in these 3 calls. Can anyone explain what difference it makes to the flow of the application? Is it only useful when the calling thread is the main GUI thread?

static async Task Main(string[] args)
{
    WriteText();

    await WriteTextAsync();

    WriteTextAsync().Wait();
}

static void WriteText()
{
    Thread.Sleep(3_000);
    Console.WriteLine("Hello");
}

static async Task WriteTextAsync()
{
    await Task.Run(() =>
    {
        Thread.Sleep(3_000);
        Console.WriteLine("Hello");
    });
}

Ps: If the calling thread of the method is waiting for the method to finish anyway it might as well be a normal call?

Jiji
  • 69
  • 7
  • 1
    That author is too lazy to print out the thread ID as part of `Console.WriteLine`, as with that you can almost immediately see the differences. – Lex Li Dec 15 '18 at 18:41
  • 2
    @LexLi Besides that, I don't think just using Thread.Sleep in a Console is good enough to show the actual added advantages. Besides, using `Task.Run` to call `Thread.Sleep`? Not my favorite example... – Camilo Terevinto Dec 15 '18 at 18:44
  • 2
    @CamiloTerevinto I agree. async/await is never an easy concept to master, and bad examples can mislead. – Lex Li Dec 15 '18 at 18:46
  • I added the ThreadId output to the WriteLines. Although, the thread ids seem to change rather randomly. – Jiji Dec 15 '18 at 18:48
  • Please narrow down the question to a more concrete one. As it stands now, it is too broad for a Q&A site since any answer you get you will likely respond with "yes, but what if" or "yes, but what about". – Lasse V. Karlsen Dec 15 '18 at 18:58
  • 1
    It simply is a bad example. It can teach you something about the 'how' but nothing about the 'why' of things. Keep reading or find a better source. – H H Dec 15 '18 at 19:03
  • 1
    Particularly your given example will not get the benefit of a `sync-await`. – Moshi Dec 15 '18 at 19:08
  • There are plenty of existing discussions about "why async" like https://stackoverflow.com/questions/18298946/why-use-async-await-over-normal-threading-or-tasks and https://stackoverflow.com/questions/42624647/why-use-async-when-i-have-to-use-await ... Since you've likely already read many of those it is not clear what kind of help you are looking for in this question. – Alexei Levenkov Dec 15 '18 at 20:02

3 Answers3

1

As my understanding about your question is

If the program waits for the response in await WriteTextAsync() line then what will be the benifit?

For client applications, such as Windows Store, Windows desktop and Windows Phone apps, the primary benefit of async is responsiveness. These types of apps use async chiefly to keep the UI responsive. For server applications, the primary benefit of async is scalability.

I will try to explain from the web-app point of view.

Suppose you have a web application depends on external resources like database call, when a client initiates a request ASP.NET takes one of its thread pool threads and assigns it to that request. Because it’s written synchronously, the request handler will call that external resource synchronously. This blocks the request thread until the call to the external resource returns. Figure 1 illustrates a thread pool with two threads, one of which is blocked waiting for an external resource.

enter image description here

Figure 1 Waiting Synchronously for an External Resource

Now if third client requests at the same time then there is no thread in thread pool available to assign the third request.

In asynchronous call, thread will not be stuck rather will be released and comes back to the thread pool which will facilitates to serve the third call.

When request server activities ends linke database call ends then SynchronizationContext resumes that call and returns repose to client.

Bellow image in simple analogy of aync call

enter image description here

There is lot of things happens under the hood. I wrote this maily from Async Programming : Introduction to Async/Await on ASP.NET and my understanding. It is highly recommended to have clear understanding before using async-wait.

Moshi
  • 1,385
  • 2
  • 17
  • 36
0

When you say WriteText(), WriteText() will block your current thread until it completes, as it is synchronous.

When you say await WriteTextAsync(), you will spawn a new thread and you will not block computations that do not depend on the result of WriteTextAsync().
EDIT: According to Microsoft Docs When you say await WriteTextAsync(), the compiler schedules the rest of Main() for execution after WriteTextAsync() completes. Then the control is supposed to be returned to the caller of the async method. But who is the caller of Main()? As it turns out, there is no async Main() - it is actually the same synchronous Main() - and it's just syntactical sugar for not writing .Wait() inside it. So in this case this call is equivalent to WriteTextAsync().Wait()!

Finally, when you say WriteTextAsync().Wait(), you block your current thread again and wait for the result of WriteTextAsync().

Seva
  • 1,631
  • 2
  • 18
  • 23
  • 4
    Sorry but nothing of your second sentence is correct. No new thread will be spanned by an `await` call and since `await` is a wait, an asynchronous one but still a wait, further processing *will* be locked – Camilo Terevinto Dec 15 '18 at 18:48
  • @CamiloTerevinto Thanks for the correction - you're right. I read up on it and made an edit. – Seva Dec 15 '18 at 19:21
  • But whether `async main` exists or not is not actually relevant to this point. All applications start with a single thread, the benefit is not mainly for console applications – Camilo Terevinto Dec 15 '18 at 19:23
  • @CamiloTerevinto yes, but the question includes `async Main()`. – Seva Dec 15 '18 at 19:24
0

I'll be referring to:

//Call 1
WriteText();

//Call 2    
await WriteTextAsync();

//Call 3
WriteTextAsync().Wait();

The first call doesn't have any problem, if what you want to do is a synchronous wait. In a Console application, this is quite normal.

The problem arises in programs with a UI or those that require the best use of CPU resources, the most common case being web applications.

Call 2, using await performs an asynchronous wait for the result of WriteTextAsync. In its own, that's fine and what's considered normal. However, WriteTextAsync is a very good example of something you should never do:

static async Task WriteTextAsync()
{
    // Let's create a Thread
    await Task.Run(() =>
    {
        // just to block it completely, having it do nothing useful
        Thread.Sleep(3_000);
        Console.WriteLine("Hello");
    });
}

Rather, the author should have used:

static async Task WriteTextAsync()
{
    // Let's *not* create a new thread
    await Task.Delay(3_000);
    Console.WriteLine("Hello");
}

Maybe they were to point this out further down the line, but you didn't give us the book name to know this.

Call number 3 is what you would have to do when the calling method cannot be an async one and you have to call an async method, so:

// Think that for some reason you cannot change the signature, 
// like in the case of an interface, and an async void would make your code
// never complete correctly
static void Main(string[] args)
{
    //Call 3
    WriteTextAsync().Wait();
}

Overall, I would suggest you to find a better book. Examples are easier to understand when asynchronous code is actually required.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
  • Thank you for the explanation. I hope I stumble upon a use-case soon, so I may understand the whole reasoning behind it. – Jiji Dec 15 '18 at 19:09
  • @Jiji Not sure what you are looking to learn, but I could recommend one of the Microsoft .NET Architecture eBooks (which are free) and explain stuff pretty well: https://dotnet.microsoft.com/learn/web/aspnet-architecture – Camilo Terevinto Dec 15 '18 at 19:13
  • So according to my edited answer, I think call 2 doesn't perform an asynchronous wait - in a special `asyn Main()` case - it does `WriteTextAsync().Wait()` behind the scenes. – Seva Dec 15 '18 at 19:23
  • @pteberf That's not relevant, that's only an implementation detail that may change in the future – Camilo Terevinto Dec 15 '18 at 19:25