28

HttpClient組み込みのタイムアウト機能があり(すべて非同期であるにもかかわらず、つまり、タイムアウトはhttpリクエスト機能に直交していると見なすことができるため、一般的な非同期ユーティリティで処理できますが、それは別として)、タイムアウトが開始されると、TaskCanceledException(ラップされたAggregateException)。

TCEには、CancellationTokenに等しいが含まれていCancellationToken.Noneます。

今、私が自分のものを提供HttpClientし、CancellationTokenそれを使用して、操作が終了する(またはタイムアウトする)前に操作をキャンセルすると、まったく同じTaskCanceledException、再び。を取得しCancellationToken.Noneます。

スローされた例外だけを見て、例外CancellationTokenをチェックするコードに自分自身をアクセス可能にすることなく、タイムアウトが要求をキャンセルしたかどうかを判断する方法はまだありますか?

PSこれはバグであり、CancellationTokenどういうわけか間違って修正された可能性がありCancellationToken.Noneますか?カスタムCancellationTokenを使用してキャンセルされたTaskCanceledException.CancellationToken場合、そのカスタムトークンと同じになると思います。

編集 問題をもう少し明確にするために、オリジナルCancellationTokenSourceにアクセスして、タイムアウトとユーザーキャンセルを簡単に区別できます。

origCancellationTokenSource.IsCancellationRequested == true

ただし、例外からを取得するCancellationTokenと、間違った答えが返されます。

((TaskCanceledException)e.InnerException).CancellationToken.IsCancellationRequested == false

ここに、人気のある需要のための最小限の例があります。

public void foo()
{
    makeRequest().ContinueWith(task =>
    {
        try
        {
            var result = task.Result;
            // do something with the result;
        }
        catch (Exception e)
        {
            TaskCanceledException innerException = e.InnerException as TaskCanceledException;
            bool timedOut = innerException != null && innerException.CancellationToken.IsCancellationRequested == false;

            // Unfortunately, the above .IsCancellationRequested
            // is always false, no matter if the request was
            // cancelled using CancellationTaskSource.Cancel()
            // or if it timed out
        }
    });
}

public Task<HttpResponseMessage> makeRequest()
{
    var cts = new CancellationTokenSource();
    HttpClient client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) };
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "url");

    passCancellationTokenToOtherPartOfTheCode(cts);
    return client.SendAsync(httpRequestMessage, cts.Token);
}
4

2 に答える 2

6

受け入れられた答えは確かにこれ理論的にどのように機能するかですが、残念ながら実際IsCancellationRequestedには例外に添付されているトークンに(確実に)設定されません。

HttpClient リクエストのキャンセル - TaskCanceledException.CancellationToken.IsCancellationRequested が false になるのはなぜですか?

于 2015-03-30T18:01:20.867 に答える
4

はい、どちらも同じ例外を返します (おそらくトークンを内部で使用するタイムアウトが原因である可能性があります) が、これを行うことで簡単に把握できます。

   catch (OperationCanceledException ex)
            {
                if (token.IsCancellationRequested)
                {
                    return -1;
                }

                return -2;
            }

したがって、基本的に例外にヒットしてもトークンがキャンセルされない場合、それは通常の http タイムアウトでした

于 2013-03-01T02:03:09.843 に答える