从基方法返回Task

本文关键字:Task 返回 方法 | 更新日期: 2023-09-27 18:25:18

我仍在处理异步编程,对如何修改以下内容有点困惑:

基本虚拟方法:

public virtual async Task OnSuspendingAsync(object s, SuspendingEventArgs e)
{
     // do some housekeeping actions upon suspending in the base class
     await Task.Yield();
}

覆盖方法:

public override Task OnSuspendingAsync(object s, SuspendingEventArgs e)
{
     // do some housekeeping actions on exiting/suspending
     return base.OnSuspendingAsync(s, e);
}

问题:

现在,如果我在overrided方法中使用awaitable(几乎是不可避免的),我需要通过添加async关键字将public override Task更改为public override async Task,如下面的实际示例所示。

public override async Task OnSuspendingAsync(object s, SuspendingEventArgs e)
{
   try
   {
     // tidy up app temporary folder on exit
     await ApplicationData.Current.ClearAsync(ApplicationDataLocality.Temporary);
   }
   catch { }
   return base.OnSuspendingAsync(s, e); // this is wrong with awaitable!
}

在这种情况下,return base.OnSuspendingAsync(s, e);应该更改为什么(以及为什么)Visual Studio正确地将其标记为错误?

从基方法返回Task

您应该await结果:

public override async Task OnSuspendingAsync(object s, SuspendingEventArgs e)
{
   try
   {
     // tidy up app temporary folder on exit
     await ApplicationData.Current.ClearAsync(ApplicationDataLocality.Temporary);
   }
   catch { }
   await base.OnSuspendingAsync(s, e);
}

在方法中包含await之前,该方法可以同步运行。您可以执行同步逻辑,然后调用异步基方法,并将返回的Task对象作为自己的返回值传递给它,该对象用于跟踪其进度。

但是,一旦您将await引入到您的方法中,现在您自己的方法就是异步的。它将在第一个await返回,而返回给调用者的Task表示方法将执行的整个工作序列。

您需要确保Task不会指示完成,直到基本方法的Task本身指示完成为止。因此,在现在的异步方法中,最不需要做的就是await,它是基本方法的结果。在这样做的过程中,您的方法实际上不会在这之后终止,因此它自己的Task对象(表示它自己的工作)在基本方法终止之前不会指示完成。

请注意,这并不是解决您的场景的唯一可能方法。但是IMHO,它是可读性最高、实现最简单的。


附录:

我认为以上内容足以解释为什么使用await,但也许不是。详细说明以上内容,特别是回答"为什么returnawait取代?"的问题:

  1. 重要的是要理解return语句并不是字面意义上的被替换。在某些情况下,return await是正确的。也就是说,当async方法实际上返回了一个值,并且该值是由某个不可用的操作产生的

  2. 那么,return声明去了哪里?嗯:当您创建一个async方法时,返回类型会发生变化。方法的返回类型必须是voidTaskTask<T>(其中T当然是某个实际类型或定义的类型参数),而不是由方法使用return语句返回的实际值

    这里我们必须使用Task,因为这是我们必须遵守的方法签名。但请注意,当没有返回实际值时,我们使用Task(即,否则方法将为void)。因此,我们的async方法不能返回任何内容。您可以编写return;,但不能编写return <some value>;。我选择完全省略返回,但如果您喜欢它,可以添加return第二个await...

    之后
  3. 为什么添加await。根据我上面的解释,我希望这一点更清楚。当base.OnSuspendingAsync()方法(异步)执行它的工作时,它会导致方法的执行被暂时挂起。它与async一起工作,向编译器指示方法中的一个点,何时可以返回,然后在哪里恢复执行

    使用await可以确保OnSuspendingAsync()覆盖返回的Task在基本实现本身完成之前不会指示完成