定义ICommand为调用lambda的异步lambda或异步void?
作者:互联网
考虑以下两种设置ICommand来执行异步任务的方法(在这种情况下,使用Xamarin.Forms.Command,但是我希望这不是很关键):
方案1:将命令设置为一个异步lambda,在其中等待异步Task方法:
// Command definition
ToggleCheckedCommand = new Command(
execute: async () => { await ToggleCheckedAsync(); },
canExecute: () => !IsBusy);
// Method that is executed
private async Task ToggleCheckedAsync()
{
IsBusy = true;
await DoWork();
IsBusy = false;
}
方案2:将命令设置为异步void方法:
// Command definition
ToggleCheckedCommand = new Command(
execute: ToggleCheckedAsync,
canExecute: () => !IsBusy);
// Method that is executed
private async void ToggleCheckedAsync()
{
IsBusy = true;
await DoWork();
IsBusy = false;
}
只要一个从不直接调用ToggleCheckedAsync,这两个方案是否等效,或者与另一个方案相比有什么陷阱?
(我知道异步无效通常被认为是直接事件处理程序之外的一种不好的做法,但是从逻辑上讲ToggleCheckedAsync是一个事件处理程序,方案1中的异步lambda也是AFAIK有效的异步无效.)
解决方法:
As long as one is never calling ToggleCheckedAsync directly, are these two scenarios equivalent, or are there any gotchas with one compared to the other?
哪一个都好;它们是等效的方法.异步void在这里是适当的,因为ICommand.Execute在逻辑上是一个事件处理程序. (并且不要弄错:这两种方法都存在异步无效:第一个示例的lambda变为异步无效).
但是,在我自己的代码中,这并不成立:
As long as one is never calling ToggleCheckedAsync directly
特别是单元测试.单元测试可以直接执行您的命令,包括能够等待命令完成,而ICommand不能满足此需求.
因此,我发现公开异步Task方法很有用.或者,如果您想变得更高级,则开发一个IAsyncCommand
type with a Task ExecuteAsync
method and expose that from the ViewModel.按照该设计的逻辑结论,您可以得到full AsyncCommand
that hides the async void Execute
as an implementation detail.
标签:icommand,async-await,c 来源: https://codeday.me/bug/20191112/2024119.html