解释async再次等待

Ron*_*ean 0 .net c# async-await

这是我的事件处理程序代码:

protected async void TestrunSaveExecute()
{
    bool saveResult = await SaveTestRunAsync();
}
Run Code Online (Sandbox Code Playgroud)

为了保持UI响应,我使用了async/ await方法.

根据我的理解,我现在可以在SaveTestRunAsync()不阻止UI的情况下进行一些冗长的操作,因为它通过使用await关键字解耦.

private async Task<bool> SaveTestRunAsync()
{
    //System.Threading.Thread.Sleep(5000); --> this blocks the UI
    await Task.Delay(5000); // this doesn't block UI

    return true;
}
Run Code Online (Sandbox Code Playgroud)

你能否解释为什么Thread.Sleep仍然阻止用户界面的呼叫,而Task.Delay不是?

ang*_*son 14

代码仍在UI线程上运行.

它不是在后台线程上运行.

因此,您在异步方法中执行的任何冗长,昂贵的操作仍将阻止该时间段的UI.

Thread.Sleep 将UI线程置于休眠状态.

你需要了解如何async以及await在这种情况下工作.

await 这里基本上说这个:

我们在这里将方法拆分为两个.第一部分是任何执行到达的点await.第二部分是等待对象完成后应该执行的任何部分.

所以,基本上,该方法一直执行直到达到await Task.Delay(5000);.然后它将"延迟5秒"置于播放状态,并说"在完成后安排其余代码执行".然后它返回,以便UI线程可以保持泵送消息.

一旦5秒钟结束,UI线程将执行该方法的其余部分.

基本上,如果您执行异步I/O,这是很好的,但如果您执行昂贵的操作(如处理大型数据集或类似操作)则不太好.

那么你怎么能这样做呢?

你可以用Task.Run.

这将启动另一个线程来执行它给出的委托,并且UI线程可以在此期间自由地执行其他操作.

基本上你可以想到一个方法使用await如下:

Life of method:    <------------------------------------------------------->
Parts:             [ start of method ----][awaitable][ rest of method -----]
Run Code Online (Sandbox Code Playgroud)

因此该方法将执行第一部分,直到它到达await X,然后它将检查X是否已经完成,如果没有完成,它将Taskawaitable对象开始运行的方式设置一些对象,并且一旦完成,"方法的其余部分"开始运行.

如果X已经完成,也许它是一个已经完成的异步I/O操作,或者它完成得非常快,那么该方法将继续执行方法的其余部分,就好像你没有await在那里写的那样.

但如果没有,那么它就会回归.这很重要,因为它允许UI线程(在这种情况下)回到用户点击鼠标点击和事物等消息.

一旦等待那个"等待对象"的任务被告知等待完成,就会安排"方法的其余部分",这基本上(在这种情况下)将消息放入消息队列中,要求它执行其余部分方法.

越多await的语句,你有这样的方法,将多件,基本上它只会分裂法成多个部分.

您可以Task使用早期.NET版本中引入的类来完成所有这些操作.async/ 的全部目的await是使编写代码更容易,因为将代码包装在任务对象中会产生令人遗憾的影响,即将代码转换为异常,并使处理异常和循环等事情变得困难.

  • +1即使是初学者也可以理解它来解释它. (2认同)