-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Description
Task-returning methods on HttpClient are blocking for up to a few seconds when called for the first time, despite their documentation:
This operation doesn't block.
Reproduction Steps
var stopwatch = Stopwatch.StartNew();
Log("Start");
var task = TestHttpClient();
Log("Waiting for result...");
var result = task.Result;
Log("Length: " + result.Length);
async Task<string> TestHttpClient()
{
using var client = new HttpClient();
Log("Sending request...");
using var response = await client.GetAsync("http://example.org/");
Log("Response received.");
return await response.Content.ReadAsStringAsync();
}
void Log(string str)
{
Console.WriteLine($"{stopwatch.Elapsed.TotalSeconds:0.00} {str}");
}Expected behavior
Waiting for result... should be displayed shortly after Sending request... when the asynchronous operation starts.
Actual behavior
0.00 Start 0.07 Sending request... 6.64 Waiting for result... 6.96 Response received. 6.96 Length: 1256
Regression?
Also tested on .NET 6 and .NET Framework 4.8 with the same results.
Known Workarounds
Using Task.Run or loading HttpClient.DefaultProxy are the only options to get rid of the blocking.
Configuration
.NET 9.0.100
Other information
Debugging reveals that the blocking operation happens in HttpConnectionPoolManager, when HttpClient.DefaultProxy is requested.
Retrieving HttpClient.DefaultProxy eventually leads to WinHttpGetIEProxyConfigForCurrentUser where the majority of the blocking comes from (even if no system-wide proxy is configured). This operation is executed non-asynchronously, hence it blocks the construction of the Task.