I have an ASP.NET MVC/WebAPI application where the domain logic depends on events in certain circumstances to decouple concerns. It's becoming increasingly difficult to avoid using async methods in the event handlers, but being that this is a web application I want to avoid using async void
as these are not top level events that we're dealing with. I've seen some solutions that seem overly complex for dealing with this- I'd like to keep the solution to this simple. My solution is to ditch EventHandler
delegates and use a Func
that returns a Task
instead, e.g.:
public event EventHandler<MyEventArgs> SomethingHappened;
would be refactored to:
public event Func<object, MyEventArgs, Task> SomethingHappened;
so in my code I can do this:
if (SomethingHappened != null)
{
await SomethingHappened.Invoke(this, new MyEventArgs());
}
We're the only one consuming these projects, so using the standard convention of EventHandler
isn't absolutely necessary. While using this pattern implies knowledge that the handler is async, I'm not sure that's necessarily a bad thing as more and more libraries are dropping their synchronous API methods or simply not including them to begin with. To some extent I'm surprised this isn't supported as a first class concept within .NET with async/await becoming increasingly prevalent in many libraries that are commonly used by web applications.
This seems like an elegant solution. I've tested this in a real application with multiple subscribers to the event, with different delays for each handler, and Invoke()
awaits them all. Yet, it feels like a trap. What am I missing?