Calling an async code in a synchronous execution path leads to the calling thread being paused until the async part finishes (the corresponding Task object is marked as completed). Because of the specific implementation of async methods in C#, the Task object cannot be marked as complete until continuations are executed. In most of the scenarios, continuations are scheduled to be executed on thread pool threads. Therefore, the calling thread starts to depend on the availability of worker threads in the default thread pool.
This mostly means that calling an async API in a synchronous context needs two threads to do the job. An application must always have free threads, otherwise an endless blocking can occur due to a lack of worker threads to call continuation and unblock main thread. This design constraint could be resolved by using a custom thread scheduler that can take advantage of a blocked thread to execute the operation, thereby eliminating the need for an extra thread.
Sitecore xConnect is written according to high-performance application best practices, with optimized thread consumption. Its design allows for taking full advantage of async operation processing and it defines the custom scheduler to tackle excessive thread consumption.
Unfortunately, the recent changes in .NET Framework 4.7.2 (System.Net.Http assembly) removed the respect of custom thread schedulers. This has led to excessive thread consumption by sync-async operations.