Func<T, Task> 和匿名异步 await Action<T> 的区别

Leo*_*rci 3 c# async-await blazor

我正在 ASP.NET Core Blazor 上开发,有时我会在 GitHub 上学习一些东西。这个问题与 Blazor 并不严格相关,但我看到很多 Blazor 开发人员在做我将要解释的内容。

我注意到一些组件接受 aAction<T>作为参数,而其他组件接受Func<T, Task>.

/* example */

public class MyComponentA : ComponentBase 
{
    [Parameter] public Action<T> OnClick {get; set;}

    //... other methods
}

public class MyComponentB : ComponentBase 
{
    [Parameter] public Func<T, Task> OnClickAsync {get; set;}

    //... other methods
}

Run Code Online (Sandbox Code Playgroud)

我的理解是你应该绑定Action<T>到一个无异步/等待方法和Func<T, Task>一个异步/方法。到现在为止还挺好。

但是,我看到有人被用来传递一个异步/等待匿名函数作为Action<T>OnClick=@(async (item) => await Foo(item))。有时,我也传递了一个匿名的 async/await 函数Action,它可以工作。

  • 这是正确的吗?

  • 有什么副作用吗?

  • Action<T>调用匿名异步/等待函数的异步调用吗?

Joh*_*lay 7

Action<T>不允许返回值,并且只能等待返回可等待类型(通常为TaskTask<T>)的方法。

因此,如果您使用传递异步方法,因为Action<T>总是会被遗忘。

可能会等待使用FuncwithTask作为返回值,具体取决于方法的实现方式。


Ste*_*ary 6

有时,我也将匿名 async/await 函数作为 Action 传递,并且它有效。

编译

实际发生的情况是asynclambda 被async void编译器转换为方法,并且async void方法有问题

这是正确的吗?有什么副作用吗?

这可能是不正确的。

如果委托只是一个“通知”,那么它本质上就是一个事件,async void通常是事件可以接受的。问题是:Blazor 如何知道它的工作已经完成?Blazor 确实有一个SynchronizationContext; 但是,它SynchronizationContext检测async voidhandlers。因此 Blazor 可能会在它实际上有更多工作要做时决定它的工作已经完成。

调用匿名 async/await 函数的 Action 是异步调用吗?

是的,但它是async void,所以它不会出现异步。例如,委托调用者无法知道委托何时完成执行。