问题
Current Situation
There is a client that does a get-request by HttpClient.GetAsync. Unfortunately, for some reason, we need to block on that calls.
In order to do so, this Asynchelper class is used in order to avoid context-switch deadlocks (instead of just using .Result)
public static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static void RunSync(Func<Task> func)
{
AsyncHelper._myTaskFactory
.StartNew<Task>(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
Then the actual call looks like this:
AsyncHelper.RunSync(Async Function() Await _httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead))
Problem
During a stress test using Netlimiter to reduce the network speed, we encountered a problem with requests that did not finish. For example, when I kill a network connection (in NetLimiter), such a request will stay forever on client side. It will stay in the AsyncHelper.RunSync-call until it runs into the httpClient.Timeout.
Shouldn't there be an exception that will end this call when the connection is lost? Am I missing something?
回答1:
The thing is that HTTP connections are usually riding over a TCP connection. So when you forcefully terminate a TCP connection without its being able to send its "I'm done here," (or FIN) packets, the other end of the connection is still happy to wait for more data, at least until some defined timeout which can be configured from above in socket-query operations.
One way to handle this is to set TCP Keep-Alive on the sockets. Note that this is very different from HTTP Keep-Alive. The other option is, as already seems to happen, to use a good-enough timeout.
来源:https://stackoverflow.com/questions/35066721/c-sharp-httpclient-block-for-async-call-deadlock