Why exactly is void async bad?
Well, walking through the reasons in the "avoid async void
" article:
- Async void methods have different error-handling semantics. Exceptions escaping from
PrimeCustomTask
will be very awkward to handle. - Async void methods have different composing semantics. This is an argument centered around code maintainability and reuse. Essentially, the logic in
PrimeCustomTask
is there and that's it - it can't be composed into a higher-levelasync
method. - Async void methods are difficult to test. Following naturally from the first two points, it's very difficult to write a unit test covering
PrimeCustomTask
(or anything that calls it).
It's also important to note that async Task
is the natural approach. Of the several languages that have adopted async
/await
, C#/VB are the only ones AFAIK that support async void
at all. F# doesn't, Python doesn't, JavaScript and TypeScript don't. async void
is unnatural from a language design perspective.
The reason async void
was added to C#/VB was to enable asynchronous event handlers. If you change your code to use async void
event handlers:
protected override async void OnLoad(EventArgs e)
{
if (CustomTask == null)
await PrimeCustomTask();
}
private async Task PrimeCustomTask()
Then the async void
disadvantages are restricted to your event handler. In particular, exceptions from PrimeCustomTask
are propagated naturally to its (asynchronous) callers (OnLoad
), PrimeCustomTask
can be composed (called naturally from other asynchronous methods), and PrimeCustomTask
is much easier to include in a unit test.
Using void async is only generally seen as "bad" because:
- You can’t wait for its completion (as mentioned in this post already
- Is especially painful if it is called by a parent thread that exits before it has completed
- Any unhandled exceptions will terminate your process (ouch!)
There are plenty of cases (like yours) where using it is fine. Just be cautious when using it.