提问人:Youssef Bennour Sahli 提问时间:9/12/2023 最后编辑:Youssef Bennour Sahli 更新时间:9/14/2023 访问量:182
如何从委托中解脱异步函数 [重复]
How to unchain asynchronous functions from delegates [duplicate]
问:
我正在处理一个 Blazor 服务器项目,我有一个存储库服务,我从中执行数据库操作,我有一个使用该服务的 razor 组件 X。
基本上,我想在存储库服务中触发某些操作(如添加、更新、删除)的事件,以通知 razor 组件 X 有新的更改。 下面是存储库服务中的事件声明:
Public event Action? SomethingChanged;
我在每个 crud 操作上都调用该事件。 在组件 X 中,我使用异步方法链接该事件(来自存储库服务),如果我使用以下语法执行它,该方法可以正常工作:
protected override OnInitalized()
{
RepositoryService.SomethingChanged += async () => await AnAsynchronousMethod();
}
我的问题是我无法从事件中取消该异步方法的链接,因为据我所知,以下代码:
public void Dispose()
{
RepositoryService.SomethingChanged -= async () => await AnAsynchronousMethod();
}
将无法解开异步方法的链接(因为匿名方法将尝试在后台创建另一个方法)。
也许您会发现使用事件来接收更新通知是不合理的,但原因是我这样做是因为我正在将该存储库服务注入另一个组件 Y 中。 在组件 Y 中使用存储库服务所做的更改需要在实际组件 X 中生效。
有没有办法克服这个问题,或者有没有其他你认为更有效的方法。
答:
2赞
Jon Skeet
9/12/2023
#1
只需创建一个方法,以便您可以使用方法组转换而不是 lambda 表达式。假设事件是用委托类型(如此同步)声明的,你需要这样的东西:Action
protected override OnInitalized() =>
RepositoryService.SomethingChanged += InitializationHandler;
public void Dispose() =>
RepositoryService.SomethingChanged -= InitializationHandler;
// Note: async void is normally an antipattern, but it's common
// for event handlers.
private async void InitializationHandler() =>
await AnAsynchronousMethod();
评论
0赞
Youssef Bennour Sahli
9/12/2023
谢谢,这工作正常,但是“异步无效”方法签名会导致一些问题,例如丢失堆栈跟踪。如果是这样,你认为我应该关注这一点吗,你是否推荐任何其他方法来解决我上面描述的问题,一种更优雅的方法。
2赞
Jon Skeet
9/12/2023
@YoussefBennourSahli:你认为这会导致 lambda 表达式没有引起的问题吗?lambda 表达式基本上在做同样的事情......这只是从同步方法调用异步方法的产物。
1赞
ℍ ℍ
9/12/2023
#2
这要简单得多:
protected override void OnInitalized()
{
RepositoryService.SomethingChanged += AnAsynchronousMethod; // no ()
}
public void Dispose()
{
RepositoryService.SomethingChanged -= AnAsynchronousMethod;
}
您不想在订阅时调用该方法,因此类似于 。async/await 也可以省略。()
address-of
AnAsynchronousMethod()
可以(应该)是 .您的代码建议它返回一个 Task,但在引发事件时不可能(可靠)等待它。async void
我正在使用操作类型的事件
那么你确实必须包装它。
async void UpdateHandler() // for += and -=
{
await InvokeAsync(AnAsynchronousMethod);
await InvokeAsync(StateHasChanged);
}
评论
0赞
Youssef Bennour Sahli
9/12/2023
抱歉,我没有提到我正在使用 Action 类型的事件,因此它不以这种方式接受它。
0赞
Youssef Bennour Sahli
9/12/2023
它确实适用于异步无效任务,但是如果我要直接链接“异步任务”,那是不可能的,因为我使用的是 Aciton,在这种情况下,我应该切换到具有返回类型的委托类型。
评论