从基方法返回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正确地将其标记为错误?
您应该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
,但也许不是。详细说明以上内容,特别是回答"为什么return
被await
取代?"的问题:
- 重要的是要理解
return
语句并不是字面意义上的被替换。在某些情况下,return await
是正确的。也就是说,当async
方法实际上返回了一个值,并且该值是由某个不可用的操作产生的 - 那么,
return
声明去了哪里?嗯:当您创建一个async
方法时,返回类型会发生变化。方法的返回类型必须是void
、Task
或Task<T>
(其中T
当然是某个实际类型或定义的类型参数),而不是由方法使用return
语句返回的实际值
这里我们必须使用Task
,因为这是我们必须遵守的方法签名。但请注意,当没有返回实际值时,我们使用Task
(即,否则方法将为void
)。因此,我们的async
方法不能返回任何内容。您可以编写return;
,但不能编写return <some value>;
。我选择完全省略返回,但如果您喜欢它,可以添加return
在第二个await...
之后 - 为什么添加
await
。根据我上面的解释,我希望这一点更清楚。当base.OnSuspendingAsync()
方法(异步)执行它的工作时,它会导致方法的执行被暂时挂起。它与async
一起工作,向编译器指示方法中的一个点,何时可以返回,然后在哪里恢复执行
使用await
可以确保OnSuspendingAsync()
覆盖返回的Task
在基本实现本身完成之前不会指示完成