[英].NET HttpClient - cancelled CancellationToken not cancelling request
I'm running into an issue with the .NET HttpClient
class (.NET 4.5.1, System.Net.Http v4.0.0.0). 我遇到了.NET
HttpClient
类(.NET 4.5.1,System.Net.Http v4.0.0.0)的问题。 I'm calling HttpClient.GetAsync
, passing in a CancellationToken
(as part of a Nuget package that abstracts calls between webservices). 我正在调用
HttpClient.GetAsync
,传入一个CancellationToken
(作为Nuget包的一部分,用于抽象webservices之间的调用)。 If the token has been cancelled before the call is made, the request goes through without throwing an exception. 如果在进行调用之前已取消令牌,则请求将在不抛出异常的情况下通过。 This behavior doesn't seem correct.
这种行为似乎不正确。
My test (incomplete, not fully written - no exception check): 我的测试(不完整,未完全编写 - 无异常检查):
[TestMethod]
public async Task Should_Cancel_If_Cancellation_Token_Called()
{
var endpoint = "nonexistent";
var cancellationTokenSource = new CancellationTokenSource();
var _mockHttpMessageHandler = new MockHttpMessageHandler();
_mockHttpMessageHandler
.When("*")
.Respond(HttpStatusCode.OK);
var _apiClient = new ApiClientService(new HttpClient(_mockHttpMessageHandler));
cancellationTokenSource.Cancel();
var result = await _apiClient.Get<string>(endpoint, null, cancellationTokenSource.Token);
}
The method I'm testing: 我正在测试的方法:
public async Task<T> Get<T>(string endpoint, IEnumerable<KeyValuePair<string, string>> parameters = null, CancellationToken cancellationToken = default(CancellationToken))
{
var builder = new UriBuilder(Properties.Settings.Default.MyEndpointHost + endpoint);
builder.Query = buildQueryStringFromParameters(parameters);
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// After this, we really shouldn't continue.
var request = await _httpClient.GetAsync(builder.Uri, cancellationToken);
if (!request.IsSuccessStatusCode)
{
if (request.StatusCode >= HttpStatusCode.BadRequest && request.StatusCode < HttpStatusCode.InternalServerError)
{
throw new EndpointClientException("Service responded with an error message.", request.StatusCode, request.ReasonPhrase);
}
if (request.StatusCode >= HttpStatusCode.InternalServerError && (int)request.StatusCode < 600)
{
throw new EndpointServerException("An error occurred in the Service endpoint.", request.StatusCode, request.ReasonPhrase);
}
}
var json = await request.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception ex)
{
throw;
}
}
I know that I can check the status of the cancellation token before calling HttpClient.GetAsync
and throw if cancellation has been requested. 我知道我可以在调用
HttpClient.GetAsync
之前检查取消令牌的状态,并在请求取消时抛出。 I know that I can also register a delegate to cancel the HttpClient request. 我知道我也可以注册一个委托来取消HttpClient请求。 However, it seems as though passing the token to the HttpClient method should take care of this for me (or, else, what's the point?) so I'm wondering if I'm missing something.
然而,似乎将令牌传递给HttpClient方法应该为我处理这个问题(或者,除此之外,重点是什么?)所以我想知道我是否遗漏了一些东西。 I don't have access to the
HttpClient
source code. 我无权访问
HttpClient
源代码。
Why is HttpClient.GetAsync
not checking my cancellation token and aborting its process when I pass it in? 为什么
HttpClient.GetAsync
在我传递它时不检查我的取消令牌并中止其进程?
HttpClient
doesn't check the cancellation token itself, it passes it on to the message handler when it calls its SendAsync
method. HttpClient
不检查取消令牌本身,它在调用其SendAsync
方法时将其传递给消息处理程序。 It then registers to the continuation on the task returned from SendAsync
and will set its own task as cancelled if the task returned from the message handler was cancelled. 然后它注册到
SendAsync
返回的任务的延续,如果从消息处理程序返回的任务被取消,它将自己的任务设置为取消。
So the problem in your scenario is in your implementation of MockHttpMessageHandler
which seems doesn't check the cancellation token. 所以你的场景中的问题在于你的
MockHttpMessageHandler
的实现,它似乎没有检查取消令牌。
Note, that if HttpClient
is called via its empty constructor, it internally uses HttpClientHandler
which registers a delegate on the cancellation token that aborts the request and cancels the task. 注意,如果通过其空构造函数调用
HttpClient
,它会在内部使用HttpClientHandler
,它会在取消令牌上注册一个委托,该委托取消该请求并取消该任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.