C# httpClient (блок для асинхронного вызова) тупик

Текущая ситуация

Есть клиент, который выполняет запрос get от HttpClient.GetAsync. К сожалению, по какой-то причине нам нужно заблокировать эти звонки.

Для этого этот класс Asynchelper используется для того, чтобы избежать взаимоблокировок с переключением контекста (вместо того, чтобы просто использовать.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();
    }
}

Тогда фактический вызов выглядит так:

AsyncHelper.RunSync(Async Function() Await _httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead))

проблема

Во время стресс-теста с использованием Netlimiter для снижения скорости сети мы столкнулись с проблемой с запросами, которые не были завершены. Например, когда я отключаю сетевое соединение (в NetLimiter), такой запрос навсегда останется на стороне клиента. Он будет оставаться в вызове AsyncHelper.RunSync до тех пор, пока не попадет в httpClient.Timeout.

Не должно ли быть исключение, которое завершит этот вызов при потере соединения? Я что-то пропустил?

1 ответ

Решение

Дело в том, что HTTP-соединения обычно проходят через TCP-соединение. Поэтому, когда вы принудительно завершаете TCP-соединение, не имея возможности отправлять свои пакеты "Я закончил" (или FIN), другой конец соединения по-прежнему рад ждать дополнительных данных, по крайней мере, до некоторого определенного времени ожидания. который можно настроить сверху в операциях запроса сокета.

Один из способов справиться с этим - установить TCP Keep-Alive для сокетов. Обратите внимание, что это сильно отличается от HTTP Keep-Alive. Другой вариант, как уже кажется, использовать достаточно хороший тайм - аут.

Другие вопросы по тегам