web-dev-qa-db-ja.com

.NETでHttpClient.Timeoutを動的に変更する

リクエストを行った後、HttpClient.Timeoutプロパティを変更する必要があります。試してみると、例外が発生します。

このインスタンスはすでに1つ以上のリクエストを開始しています。プロパティは、最初のリクエストを送信する前にのみ変更できます。

これを回避する方法はありますか?

18
AsValeO

これを変更するためにできることはあまりありません。これは、HttpClient実装のデフォルトの動作です。

GetRequestStreamまたはGetResponseメソッドを呼び出す前に、Timeoutプロパティを設定する必要があります。 HttpClient.Timeout注釈セクションから

タイムアウトを変更するには、HttpClientの新しいインスタンスを作成するのが最善です。

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

内部的には、Timeoutプロパティを使用してCancellationTokenSourceを設定し、タイムアウトに達すると非同期操作を中止します。 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();
    }
}
6
Monsignor

カスタムリクエストレベルのタイムアウトのサポートの欠如は、私の心の中で常にHttpClientの欠点でした。小さなライブラリの依存関係を気にしないのであれば、 Flurl.Http [免責事項:私は作者です]はこれを直接サポートしています:

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

これは真のリクエストレベルの設定です。同じホストへのすべての呼び出しは、内部で共有HttpClientインスタンスを使用し、タイムアウトが異なる同時呼び出しは競合しません。構成可能なグローバルデフォルトがあります(最初は100秒、HttpClientと同じ)。

5
Todd Menier