Tod*_*ier 30 .net c# async-await cancellationtokensource dotnet-httpclient
给出以下代码:
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");
}
Run Code Online (Sandbox Code Playgroud)
我希望ex.CancellationToken.IsCancellationRequested是true在catch块内,但事实并非如此.我误会了什么吗?
i3a*_*non 43
情况就是这样,因为HttpClient内部(in SendAsync)使用a TaskCompletionSource来表示async操作.它返回TaskCompletionSource.Task,这是你的任务await.
然后base.SendAsync,它会在返回的任务上调用并注册一个延续,从而相应地取消/完成/排除TaskCompletionSource任务.
在取消的情况下,它使用TaskCompletionSource.TrySetCanceled将取消的任务与new CancellationToken(default(CancellationToken))相关联.
你可以通过查看来看到TaskCanceledException.在顶部ex.CancellationToken.IsCancellationRequested的存在false ex.CancellationToken.CanBeCanceled也是false,这意味着这CancellationToken因为它不使用创建不能被取消CancellationTokenSource.
IMO应该使用它TaskCompletionSource.TrySetCanceled(CancellationToken).这样,TaskCompletionSource它将与CancellationToken消费者传入而不仅仅是默认值相关联CancellationToken.我认为这是一个错误(虽然是一个小错误),我提交了关于它的连接问题.