Migrate from blocking .Result/.Wait() calls to async all the way up in a legacy C# codebase
A staged playbook for removing sync-over-async from an existing .NET codebase: inventory with analyzers, measure ThreadPool starvation, convert one call chain at a time, and ratchet the count to zero on .NET 11.