从基础方法

时间:2015-12-02 14:07:24

标签: c# asynchronous windows-runtime async-await uwp

我仍在处理异步编程问题,并对如何修改以下内容感到困惑:

基本虚拟方法:

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

问题:

现在,如果我在重写方法中使用等待(几乎不可避免),我需要通过添加public override Task关键字将public override async Task更改为async,如下图所示。

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正确标记为错误?

1 个答案:

答案 0 :(得分:3)

你应该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对象(代表它自己的工作)将不会指示完成,直到基本方法为止。

请注意,这不是解决方案的唯一可行方法。但恕我直言,它是最易读和易于实施的。


附录:

我认为上述内容足以解释为什么使用await,但也许没有。要详细说明上述内容,特别是回答“为什么return替换为await?”的问题:

  1. 了解return语句不是字面上被替换是很重要的。在某些情况下,return await是正确的。即当async方法确实返回一个值并且该值是由某个等待操作产生的时候。

  2. 那么return声明在哪里?好吧:当您创建async方法时,返回类型会更改。方法的返回类型必须是returnvoidTask(其中Task<T>,而不是带有T语句的方法返回的实际值。当然是一些实际类型或定义的类型参数)。

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

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

    使用await确保{ Task覆盖返回的{1}}表示在基础实现完成之前未指示完成。