TL;DR: Use Lindhart.Analyser.MissingAwaitWarning to get warnings on all ignored Tasks
We all know and love compiler warning CS4014 for ignoring Tasks.
You would think that this warning triggers every time we ignore a Task
instead of awaiting it, calling Wait()
or Result
on it or propagate it to the caller.
Well, that is in fact not the case.
The documentation on CS4014 states the actual prerequisites for this warning to show up:
The current method calls an async method that returns a Task or a Task<TResult> and doesn’t apply the await operator to the result.
There is no warning when the method returning the Task is not async
.
In particular this includes interface methods (!).
People did open issues to add a warning for all ignored Tasks, but those were turned down because the async
prerequisite was not an oversight but a design decision.
The reason is apparently that Task
predates async
and having the compiler issue a warning on all ignored Tasks would have added too much noise to legacy code bases.
Not having this warning can lead to undetected errors when migrating a code base from synchronous calls to asynchronous calls, e. g. migrating an ASP.NET MVC application to use asynchronous repository methods.
There will be no warning for calling e. g. Task MyMethodAsync(...)
on ISomeRepository
or ISomeDomainService
and ignoring the returned Task.
The calling method will potentially return early, leading to all kinds of potential consistency and timing problems.
Luckily, there is an analyzer package allowing us to enable a warning on all ignored Tasks: Lindhart.Analyser.MissingAwaitWarning.
I am not yet sure if the package is stable enough to keep to avoid future mistakes, but at the very least it was useful as a one-off analyzer to fix all remaining ignored Tasks after the initial async migration.