试图理解 async 和 await [重复]

Posted

技术标签:

【中文标题】试图理解 async 和 await [重复]【英文标题】:Trying to understand async and await [duplicate] 【发布时间】:2019-03-04 16:16:40 【问题描述】:

示例代码。在下面的 async 方法中,IndexAsync 方法实际上是否可以在相应的 Get* 方法完成之前返回?我试图了解异步和等待的基础知识,就像作者提到他也在做的那样。

感谢代码作者: https://www.exceptionnotfound.net/using-async-and-await-in-asp-net-what-do-these-keywords-mean/

所以,根据我现在的理解,以下是否属实: Async 方法的好处是,当执行到 Get* 方法的调用时,它们不必等待,所以后面的代码可以执行,当 Get* 方法最终返回它们的值时,IndexAsync 最终可以返回。总结一下?

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");
    

【问题讨论】:

【参考方案1】:

当遇到await 时,进程暂停,控制权交还给调用方法。等待的操作既不会阻塞也不会被执行(直到稍后)。

我建议查看这个有用的 msdoc 示例。

【讨论】:

谢谢。链接中的流程图确实很有帮助。【参考方案2】:

当您调用非异步调用时,这些调用只是普通调用。执行移至GetContent 之类的方法,并且您正在运行的线程休眠规定的毫秒数。调用依次执行,但线程只是在每次调用时休眠

您的IndexAsync 方法声明为async。它在幕后构建了一个用于执行异步代码的小型状态机。

当您调用 service.GetContentAsync(); 时,它会调用 GetContentAsync,但所发生的只是函数开始执行,然后,当它到达 await Task.Delay(3000); 时,它返回一个承诺(到 IndexAsync)以完成执行稍后(由该任务表示)。

稍后,你await 任务。这会调用那个状态机。该方法的其余部分(在等待之后)被包装在一个 lambda 中,并在 Task 发出完成信号时排队执行。但是,您的代码的执行被暂停,并且您正在运行的线程被释放回线程池(或它来自的其他任何地方)。例如,如果它是 WinForms 或 WPF 应用程序中的 UI 线程,它将返回为 UI 提供服务。

任务完成后,其余代码将再次开始运行。在 UI 应用程序(如 WinForms 或 WPF)中,可以保证如果您在 UI 线程上启动,其余代码将在同一线程上运行。在其他环境中,保证可能涉及的更少。

如果您曾经使用 javascript 编写过网页并向服务器进行了 AJAX 调用,那么您需要设置要调用的位置、参数是什么以及调用返回时要运行的函数。 awaited 方法调用(或 awaiting 任务)有点像这样。它使用参数调用函数,但将当前函数的其余部分包装在一个表单中,该表单将在任务完成时执行。

在 UI 应用程序中异步/等待的好处是显而易见的 - 它允许顺序编程,同时仍然从 UI 线程中获得处理。

它在 ASP.NET 环境中不太明显。线程是 Web 服务器应用程序中的宝贵商品。 async/await 在 Web 应用程序中为您提供的是一种在不占用与请求相关联的线程的情况下进行后台处理的方式(其中大部分是自然异步的——比如对某些服务的 WebAPI 请求)。当您等待任务时,您的线程会回到池中。任务完成后,您的代码会返回一个线程并继续使用

【讨论】:

以上是关于试图理解 async 和 await [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Parallel.ForEach 和 async-await [重复]

JavaScript async/await:await 是保留字 [重复]

Angular 8 - 如何使用 Promises 和 Async/Await [重复]

使用 Javascript(以及 Node.js)使用 async/await 和 Promises 的正确方法是啥 [重复]

为啥 async/await Axios 请求不会返回 Data 而不是 Promise 对象 [重复]

我可以在 C# 中使用 async/await inline [重复]