示例代码。在下面的异步方法中,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");
}
}
答案 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请求),而无需占用与该请求关联的线程。等待任务时,线程将返回到池中。任务完成后,您的代码将返回一个线程并结束操作