Подтвердить что ты не робот

Отмена запроса HttpClient - Почему TaskCanceledException.CancellationToken.IsCancellationRequested false?

С учетом следующего кода:

var cts = new CancellationTokenSource();

try 
{
    // get a "hot" task
    var task = new HttpClient().GetAsync("http://www.google.com", cts.Token);

    // request cancellation
    cts.Cancel();

    await task;

    // pass:
    Assert.Fail("expected TaskCanceledException to be thrown");
}
catch (TaskCanceledException ex) 
{
    // pass:
    Assert.IsTrue(cts.Token.IsCancellationRequested,
        "expected cancellation requested on original token");

    // fail:
    Assert.IsTrue(ex.CancellationToken.IsCancellationRequested,
        "expected cancellation requested on token attached to exception");
}

Я бы ожидал, что ex.CancellationToken.IsCancellationRequested будет true внутри блока catch, но это не так. Я что-то не понимаю?

4b9b3361

Ответ 1

В этом случае, поскольку HttpClient внутри (в SendAsync) использует TaskCompletionSource для представления операции async. Он возвращает TaskCompletionSource.Task и что задача await включена.

Затем он вызывает base.SendAsync и регистрирует продолжение в возвращаемой задаче, которая соответственно отменяет/завершает/вызывает задачу TaskCompletionSource.

В случае отмены используется TaskCompletionSource.TrySetCanceled, который связывает отмененную задачу с новым CancellationToken (default(CancellationToken)).

Это можно увидеть, посмотрев на TaskCanceledException. В верхней части ex.CancellationToken.IsCancellationRequested находится false ex.CancellationToken.CanBeCanceled также false, что означает, что этот CancellationToken никогда нельзя отменить, поскольку он не был создан с помощью CancellationTokenSource.


IMO следует использовать TaskCompletionSource.TrySetCanceled(CancellationToken). Таким образом, TaskCompletionSource будет связан с CancellationToken, переданным потребителем, а не просто по умолчанию CancellationToken. Я думаю, что это ошибка (хотя и небольшая), и я отправил вопрос о подключении об этом.