从基本方法返回任务
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
?":
- 请务必了解
return
语句并非 字面意思 被替换。在某些情况下,return await
是正确的。 IE。当 async
方法实际上 return 一个值并且该值是由一些可等待的操作产生的。
- 那么
return
语句去哪儿了?嗯:当你创建一个 async
方法时,return 类型会改变。方法的 return 类型必须是 void
、Task
或 [=32],而不是由具有 return
语句的方法 return 编辑的实际值=](其中 T
当然是一些实际类型或定义的类型参数)。
这里我们必须使用 Task
因为这是我们必须遵守的方法签名和。但请注意,当没有实际值被 return 编辑时,我们使用 Task
(即该方法否则为 void
)。所以我们的 async
方法不能 return 任何东西。你可以写return;
,但不能写return <some value>;
。我选择完全省略 return,但如果您喜欢它,可以添加 return
; 在之后第二个await...
- 为什么添加了
await
。根据我上面的解释,我希望这更清楚。这是导致方法的执行在 base.OnSuspendingAsync()
方法正在执行它的工作(异步)时暂时暂停的原因。它与 async
一起工作,向编译器指示方法中的一个点,它可以 return,然后指示下一个执行将在何处继续。
使用 await
是确保 Task
return 由您的 OnSuspendingAsync()
覆盖不指示完成,直到基本实现本身完成。
我还在掌握异步编程的过程中,对如何修改以下内容有点困惑:
基本虚方法:
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
?":
- 请务必了解
return
语句并非 字面意思 被替换。在某些情况下,return await
是正确的。 IE。当async
方法实际上 return 一个值并且该值是由一些可等待的操作产生的。 - 那么
return
语句去哪儿了?嗯:当你创建一个async
方法时,return 类型会改变。方法的 return 类型必须是void
、Task
或 [=32],而不是由具有return
语句的方法 return 编辑的实际值=](其中T
当然是一些实际类型或定义的类型参数)。
这里我们必须使用Task
因为这是我们必须遵守的方法签名和。但请注意,当没有实际值被 return 编辑时,我们使用Task
(即该方法否则为void
)。所以我们的async
方法不能 return 任何东西。你可以写return;
,但不能写return <some value>;
。我选择完全省略 return,但如果您喜欢它,可以添加return
; 在之后第二个await...
- 为什么添加了
await
。根据我上面的解释,我希望这更清楚。这是导致方法的执行在base.OnSuspendingAsync()
方法正在执行它的工作(异步)时暂时暂停的原因。它与async
一起工作,向编译器指示方法中的一个点,它可以 return,然后指示下一个执行将在何处继续。
使用await
是确保Task
return 由您的OnSuspendingAsync()
覆盖不指示完成,直到基本实现本身完成。