ASP.NET 的可等待事件处理程序委托

如何解决ASP.NET 的可等待事件处理程序委托

我有一个 ASP.NET MVC/WebAPI 应用程序,其中域逻辑在某些情况下依赖于事件来解耦问题。在事件处理程序中避免使用异步方法变得越来越困难,但由于这是一个 Web 应用程序,我想避免使用 async void,因为这些不是我们正在处理的顶级事件。我已经看到一些解决方案对于处理这个问题似乎过于复杂 - 我想保持这个简单的解决方案。我的解决方案是放弃 EventHandler 委托并使用返回 FuncTask,例如:

public event EventHandler<MyEventArgs> SomethingHappened;

将被重构为:

public event Func<object,MyEventArgs,Task> SomethingHappened;

所以在我的代码中我可以这样做:

if (SomethingHappened != null)
{
    await SomethingHappened.Invoke(this,new MyEventArgs());
}

我们是唯一使用这些项目的人,因此使用 EventHandler 的标准约定并不是绝对必要的。虽然使用这种模式意味着知道处理程序是异步的,但我不确定这是否一定是件坏事,因为越来越多的库正在放弃它们的同步 API 方法或根本不包括它们。在某种程度上,我很惊讶这在 .NET 中并没有被支持作为一流的概念,因为 async/await 在许多 Web 应用程序常用的库中变得越来越普遍。

这似乎是一个优雅的解决方案。我已经在具有多个事件订阅者的真实应用程序中对此进行了测试,每个处理程序具有不同的延迟,并且 Invoke() 等待它们全部。然而,这感觉就像一个陷阱。我错过了什么?

解决方法

然而,这感觉就像一个陷阱。我错过了什么?

这部分不正确:

Invoke() 等待它们。

来自the docs

一个委托实例的调用,其调用列表包含多个条目,通过调用调用列表中的每个方法,同步地,按顺序......如果委托调用包含输出参数或返回值,它们的最终值将出现来自列表中最后一个委托的调用。

因此,Invoke 将调用所有处理程序,但仅从 last 处理程序返回 Task。其他返回的任务将被忽略。这是非常糟糕的(尝试从被忽略的任务之一抛出异常)。

相反,您应该调用 GetInvocationList 来获取处理程序列表,调用每个处理程序,然后使用 await 将它们全部 Task.WhenAll

var args = new MyEventArgs();
var tasks = SomethingHappened.GetInvocationList()
    .Cast<Func<object,MyEventArgs,Task>>()
    .Select(handler => handler(this,args))
    .ToList();
await Task.WhenAll(tasks);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?