问题描述
由于以下code:
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块内,但事实并非如此。我误解的东西吗?
I would expect ex.CancellationToken.IsCancellationRequested
to be true
inside the catch block, but it is not. Am I misunderstanding something?
推荐答案
是这样的话,因为的HttpClient
内部(在 SendAsync
)使用的是 TaskCompletionSource
来重新present的异步
操作。它返回 TaskCompletionSource.Task
,这就是你等待
上的任务
That's the case because HttpClient
internally (in SendAsync
) is using a TaskCompletionSource
to represent the async
operation. It returns TaskCompletionSource.Task
and that's the task you await
on.
,然后调用 base.SendAsync
并注册一个延续上返回的任务取消/完成/故障 TaskCompletionSource
的任务,相应地。
It then calls base.SendAsync
and registers a continuation on the returned task that cancels/completes/faults the TaskCompletionSource
's task accordingly.
在取消的情况下使用 TaskCompletionSource.TrySetCanceled
其中的关联取消的任务有一个新的的CancellationToken
(默认(的CancellationToken)
)。
In the case of cancellation it uses TaskCompletionSource.TrySetCanceled
which associates the canceled task with a new CancellationToken
(default(CancellationToken)
).
您可以看到,通过查看 TaskCanceledException
。在 ex.CancellationToken.IsCancellationRequested
是假
ex.CancellationToken.CanBeCanceled $上方C $ C>也是
假
,这意味着该的CancellationToken
,因为它不是用一个创建不能被取消 CancellationTokenSource
。
You can see that by looking at the TaskCanceledException
. On top of ex.CancellationToken.IsCancellationRequested
being false
ex.CancellationToken.CanBeCanceled
is also false
, meaning that this CancellationToken
can never be canceled as it wasn't created using a CancellationTokenSource
.
IMO应该使用 TaskCompletionSource.TrySetCanceled(的CancellationToken)
代替。这样的 TaskCompletionSource
将与的CancellationToken
通过在由消费者,而不是简单地默认<$ C $相关C>的CancellationToken 。我认为这是一个错误(虽然未成年人之一),我在连接年提交了一份问题>这件事。
IMO it should be using TaskCompletionSource.TrySetCanceled(CancellationToken)
instead. That way the TaskCompletionSource
will be associated with the CancellationToken
passed in by the consumer and not simply the default CancellationToken
. I think it's a bug (though a minor one) and I submitted an issue on connect about it.
这篇关于取消一个HttpClient的请求 - 为什么TaskCanceledException.CancellationToken.IsCancellationRequested假的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!