试图了解异步并等待

时间:2018-09-28 16:13:56

标签: c# async-await

示例代码。在下面的异步方法中,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");
    }
}

2 个答案:

答案 0 :(得分:1)

遇到await时,将暂停进度,并将控制权交还给调用方法。等待的操作不会阻塞也不会执行(直到以后)。

我建议回顾一下这个有用的msdoc示例。

答案 1 :(得分:1)

当您呼叫非异步呼叫时,这些呼叫只是普通呼叫。执行将移至类似GetContent之类的方法,并且您正在运行的线程将以规定的毫秒数进入睡眠状态。这些调用是依次执行的,但是每次调用该线程只是 sleeping

您的IndexAsync方法被声明为async。在构建用于执行异步代码的小状态机的幕后工作是什么。

当您调用service.GetContentAsync();时,会调用GetContentAsync,但是所有发生的事情是该函数开始执行,然后当到达await Task.Delay(3000);时,它会向({{1} }),以便稍后(由该任务代表)完成执行。

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

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

如果您曾经用JavaScript编写过一个网页,并向服务器进行过AJAX调用,则可以设置要调用的位置,参数是什么以及调用返回时要运行的函数。 await方法调用(或awaited Task)有点像这样。它使用参数调用该函数,但将当前函数的其余部分包装为将在Task完成时执行的形式。

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

在ASP.NET环境中不太明显。线程是Web服务器应用程序中的宝贵商品。异步/等待在Web应用程序中为您提供的一种方法是进行后台处理(其中大多数是自然异步的,例如对某些服务的WebAPI请求),而无需占用与该请求关联的线程。等待任务时,线程将返回到池中。任务完成后,您的代码将返回一个线程并结束操作

相关问题