Can async deadlocks happen with HttpClient and IHttpClientFactory?
Can async deadlocks happen with HttpClient and IHttpClientFactory?
1 Answer
Yes, but HttpClient and IHttpClientFactory aren’t usually the cause. The common problem is blocking on an asynchronous operation with .Result or .Wait().
For example, an async method may resume after an await on the UI thread. If that thread is blocked waiting for the method to finish, the continuation can’t run, and the operation deadlocks:
async Task<string> LoadAsync(HttpClient client, string url)
{
// This continuation may need to return to the caller's synchronization context.
using var response = await client.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
// Blocking the UI thread can prevent LoadAsync from resuming on that thread.
var result = LoadAsync(client, url).Result;
Prefer to keep the call chain asynchronous:
var result = await LoadAsync(client, url);
In classic ASP.NET or UI applications, blocking can cause a true synchronization-context deadlock. ASP.NET Core generally doesn’t use that kind of synchronization context, so the same code is less likely to deadlock in that specific way—but blocking can still tie up thread-pool threads and contribute to thread starvation under load.
IHttpClientFactory manages client and handler lifetimes; it doesn’t make synchronous waiting safe. If your code already uses await throughout, look for other sources of blocking, such as locks or synchronous waits inside custom handlers.