Динамическое изменение HttpClient.Timeout в .NET.

Мне нужно изменить свойство HttpClient.Timeout после запроса (-ов) запроса. Когда я пытаюсь, я получаю исключение:

Этот экземпляр уже запустил один или несколько запросов. Свойства могут быть изменены только перед отправкой первого запроса.

Есть ли способ избежать этого?

Ответ 1

Вы не можете сделать это, чтобы изменить это. Это просто поведение по умолчанию в реализации HttpClient.

Свойство Timeout должно быть установлено до вызова метода GetRequestStream или GetResponse. Из раздела HttpClient.Timeout Remark

Чтобы изменить таймаут, было бы лучше создать новый экземпляр HttpClient.

client = new HttpClient();
client.Timeout = 20; //set new timeout

Ответ 2

Внутренне свойство Timeout используется для установки a CancellationTokenSource, который прервет операцию async, когда этот тайм-аут будет достигнут. Поскольку некоторые перегрузки методов HttpClient принимают CancellationTokens, мы можем создавать вспомогательные методы для получения пользовательских тайм-аутов для определенных операций:

public async Task<string> GetStringAsync(string requestUri, TimeSpan timeout)
{
    using (var cts = new CancellationTokenSource(timeout))
    {
        HttpResponseMessage response = await _httpClient.GetAsync(requestUri, cts.Token)
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadAsStringAsync();
    }
}

Ответ 3

Отсутствие поддержки пользовательских тайм-аутов на уровне запросов всегда было недостатком HttpClient, на мой взгляд. Если вы не возражаете против небольшой зависимости от библиотеки, Flurl.Http [отказ от ответственности: я автор] поддерживает это напрямую:

"http://api.com/endpoint".WithTimeout(30).GetJsonAsync<T>();

Это истинный параметр уровня запроса; все вызовы одного и того же хоста используют общий экземпляр HttpClient под капотом, а одновременные вызовы с разными тайм-аутами не будут конфликтовать. Там настраивается глобальное значение по умолчанию (сначала 100 секунд, так же как HttpClient).