0

Sample code. In the async method below, could the IndexAsync method actually return before the corresponding Get* methods finish? Im trying to understand the basics of async and await, much like the author mentions he was also doing.

Credit to author for code: https://www.exceptionnotfound.net/using-async-and-await-in-asp-net-what-do-these-keywords-mean/

So, based on my understanding now, is the following true:
The benefit of the Async method is that when the execution comes to the calls of the Get* methods, they dont have to wait, so the code that follows can execute and when the Get* methods finally return their values, then the IndexAsync can finally return. That about sum it up?

public class ContentManagement
{
    public string GetContent()
    {
        Thread.Sleep(2000);
        return "content";
    }

    public int GetCount()
    {
        Thread.Sleep(5000);
        return 4;
    }

    public string GetName()
    {
        Thread.Sleep(3000);
        return "Matthew";
    }
    public async Task<string> GetContentAsync()
    {
        await Task.Delay(2000);
        return "content";
    }

    public async Task<int> GetCountAsync()
    {
        await Task.Delay(5000);
        return 4;
    }

    public async Task<string> GetNameAsync()
    {
        await Task.Delay(3000);
        return "Matthew";
    }
}



public class HomeController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        ContentManagement service = new ContentManagement();
        var content = service.GetContent();
        var count = service.GetCount();
        var name = service.GetName();

        watch.Stop();
        ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
        return View();
    }

    [HttpGet]
    public async Task<ActionResult> IndexAsync()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        ContentManagement service = new ContentManagement();
        var contentTask = service.GetContentAsync();
        var countTask = service.GetCountAsync();
        var nameTask = service.GetNameAsync();

        var content = await contentTask;
        var count = await countTask;
        var name = await nameTask;
        watch.Stop();
        ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
        return View("Index");
    }
}
bitshift
  • 6,026
  • 11
  • 44
  • 108

2 Answers2

1

When an await is encountered, progress is suspended and control is yielded back to the calling method. The awaited operation neither blocks nor is executed (until a later time).

I recommend reviewing this helpful msdoc example.

sean
  • 367
  • 2
  • 12
1

When you call your non-async calls, the calls are just normal calls. Execution moves to the methods like GetContent, and the thread that you are running on sleeps for the stated number of milliseconds. The calls are executed in turn, but the thread just sleeps on each call.

Your IndexAsync method is declared async. What that does behind the scenes in build up a little state machine for executing async code.

When you call service.GetContentAsync();, that calls GetContentAsync, but all that happens is that the function starts executing and then, when it gets to the await Task.Delay(3000);, it returns a promise (to IndexAsync) to finish the execution sometime later (represented by that Task).

Later, you await the task. That invokes the that state machine. The rest of the method (after the await) is wrapped up in a lambda and queued up to execute when the Task signals its completion. However, the execution of your code is suspended and the thread that you were running on is released back to the thread pool (or wherever else it came from). For example, if it was a UI thread in a WinForms or WPF app, it would go back to servicing the UI.

When the Task completes, the rest of the code starts running again. In UI applications (like WinForms or WPF), there's a guarantee that if you started on the UI thread, the rest of the code will run on that same thread. In other environments, the guarantee may be less involved.

If you have ever programmed a web page with JavaScript and made an AJAX call back to the server, you set up where you were going to call, what the parameters were, and a function to run when the call returned. An awaited method call (or awaiting a Task) is kinda-sorta like that. It calls the function with the parameters, but wraps up the rest of the current function in a form that will execute with the Task completes.

The benefits of async/await in a UI application are obvious - it allows sequential programming, while still geting processing off the UI thread.

It's a bit less obvious in an ASP.NET environment. Threads are precious commodities in web server applications. What async/await gives you in a web app is a way to have background processing (much of which is naturally asynchronous - say a WebAPI request to some service) without tying up the thread associated with the request. When you await a task, your thread goes back into the pool. When the task completes, you code gets a thread back and contineuse

Flydog57
  • 6,851
  • 2
  • 17
  • 18