我遇到了 .NET HttpClient
类(.NET 4.5.1、System.Net.Http v4.0.0.0)的问题。我正在调用 HttpClient.GetAsync
,传入一个 CancellationToken
(作为抽象 Web 服务之间调用的 Nuget 包的一部分)。如果在调用之前 token 已被取消,则请求将通过而不会引发异常。这种行为似乎不正确。
我的测试(不完整,未完全编写 - 无异常检查):
[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);
}
我正在测试的方法:
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;
}
}
我知道我可以在调用 HttpClient.GetAsync
之前检查取消 token 的状态,如果请求取消则抛出。我知道我也可以注册一个委托(delegate)来取消 HttpClient 请求。但是,似乎将 token 传递给 HttpClient 方法应该为我解决这个问题(或者,这有什么意义?)所以我想知道我是否遗漏了什么。我无权访问 HttpClient
源代码。
为什么 HttpClient.GetAsync
在我传入取消 token 时不检查我的取消 token 并中止其进程?
最佳答案
HttpClient
本身不检查取消 token ,它在调用其 SendAsync
方法时将其传递给消息处理程序。然后它注册到从 SendAsync
返回的任务的延续,如果从消息处理程序返回的任务被取消,它将把自己的任务设置为已取消。
所以您的场景中的问题在于您的 MockHttpMessageHandler
实现似乎没有检查取消 token 。
请注意,如果通过其空构造函数调用 HttpClient
,它会在内部使用 HttpClientHandler
,后者会在取消 token 上注册一个委托(delegate),以中止请求并取消任务。
关于c# - .NET HttpClient - 取消 CancellationToken 不取消请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34073104/