This conventional wisdom works great if you’re building something like a WPF (GUI) application, and event handlers are invoked occasionally as a result of user interaction (e.g. user presses a button, and an event fires). However, there is another class of event handlers that are invoked as part of a dispatcher loop in a third-party library. async void can be pretty dangerous in these cases.

async void Event Handlers in RabbitMQ

Let’s take the example of RabbitMQ. We’ll set up a basic publisher and consumer. A fundamental property of message queues is that messages are delivered in order, and that’s what we expect to happen.

When you call an async void method, it’s done in a fire-and-forget manner. The caller has no way of knowing whether or when the operation ended, so it just resumes execution immediately, rather than waiting for the async void method to finish. So you end up with parallel and interleaved execution such as this:

Fixing async void event handlers

Despite these problems, if you want to await in your event handler, you have to make it async void. To prevent parallel and interleaved execution, you have to lock. However, you can’t await in a lock block, so you need to use a different synchronisation mechanism such as a semaphore.

My own Dandago.Utilities provides a ScopedAsyncLock that allows you to neatly wrap the critical section in a using block:

You can Wait() or call .Result, but then you’d block the thread, losing the benefits of asynchronous calls altogether. Also using both synchronous waiting and await together is a dangerous practice leading to deadlocks.

Hi, I was simply not aware of that, but I wrote this little library to provide people with an easy package that they can install and use without having to reimplement the same code every time.

Unfortunately I don’t have time at this stage to revisit what I did almost 2 years ago, understand in depth what Stephen Toub did, and draw a comparison. However if you find any alternative solution that works well, then by all means go for it.