从基本方法返回任务

Returning a Task from a base method

我还在掌握异步编程的过程中,对如何修改以下内容有点困惑:

基本虚方法:

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

问题:

现在,如果我在重写的方法中使用等待对象(几乎不可避免),我需要通过添加 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 正确地标记为错误?

你应该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 之前,方法同步 运行 没问题。你可以做你的同步逻辑,然后调用异步基方法,只传递它用来跟踪其进度的 returned Task 对象作为你自己的 return 值。

但是一旦你将await引入到你的方法中,现在你自己的方法是异步的。它会在第一个 await 处 return,而 Task return 发送给调用者代表您的方法将执行的整个工作序列。

您要确保 Task 在基本方法的 Task 本身指示完成之前不指示完成。因此,您需要在现在的异步方法中做的最后一件事是 await 基本方法的结果。在这样做时,您的方法实际上不会在该事件发生之前终止,因此它自己的 Task 对象(代表它自己的工作)在基本方法完成之前不会指示完成。

请注意,这不是解决您的情况的唯一可能方法。但恕我直言,它是最易读且最容易实现的。


附录:

我认为以上足以解释为什么使用 await,但也许不是。详细说明以上内容,特别是回答问题 "why is return replaced by await?":

  1. 请务必了解 return 语句并非 字面意思 被替换。在某些情况下,return await 是正确的。 IE。当 async 方法实际上 return 一个值并且该值是由一些可等待的操作产生的。

  2. 那么return语句去哪儿了?嗯:当你创建一个 async 方法时,return 类型会改变。方法的 return 类型必须是 voidTask 或 [=32],而不是由具有 return 语句的方法 return 编辑的实际值=](其中 T 当然是一些实际类型或定义的类型参数)。

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

  3. 为什么添加了await。根据我上面的解释,我希望这更清楚。这是导致方法的执行在 base.OnSuspendingAsync() 方法正在执行它的工作(异步)时暂时暂停的原因。它与 async 一起工作,向编译器指示方法中的一个点,它可以 return,然后指示下一个执行将在何处继续。

    使用 await 是确保 Task return 由您的 OnSuspendingAsync() 覆盖不指示完成,直到基本实现本身完成。