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
.