给定以下代码:
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
在 catch block 内为 true
,但事实并非如此。我是不是误会了什么?
最佳答案
之所以如此,是因为 HttpClient
内部(在 SendAsync
中)使用 TaskCompletionSource
来表示 async
操作.它返回 TaskCompletionSource.Task
,这就是您等待
的任务。
然后它调用 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
。我认为这是一个错误(虽然是一个小错误),我提交了一个 issue on connect关于它。
关于c# - 取消 HttpClient 请求 - 为什么 TaskCanceledException.CancellationToken.IsCancellationRequested 为假?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29319086/