我想使用 CancellationToken
取消对 HttpClient.PostAsJsonAsync
的调用。但是,通过以下设置,对 PostAsJsonAsync
的调用无限期挂起(我让它运行了几分钟)。
CancellationTokenSource source = new CancellationTokenSource();
source.Cancel();
HttpClient client = new HttpClient();
try
{
var task = client.PostAsJsonAsync<MyObject>("http://server-address.com",
new MyObject(), source.Token);
task.Wait();
}
catch (Exception ex)
{
//Never gets hit.
}
请注意,我正在传递一个已经取消的 CancellationTokenSource
- 如果我使用 Task.Delay
取消 token 并延迟很短,我会遇到同样的问题。
我意识到我可以简单地检查 token 是否在调用之前被取消,但即便如此,如果 token 在短暂延迟后被取消,我也会遇到同样的问题,即它在方法调用之前没有被取消,而是变成了不久之后。
所以我的问题是,是什么原因造成的,我该怎么做才能解决/修复它?
编辑
对于那些寻求解决方法的人,受@Darrel Miller 的回答启发,我提出了以下扩展方法:
public static async Task<HttpResponseMessage> PostAsJsonAsync2<T>(this HttpClient client, string requestUri, T value, CancellationToken token)
{
var content = new ObjectContent(typeof(T), value, new JsonMediaTypeFormatter());
await content.LoadIntoBufferAsync();
return await client.PostAsync(requestUri, content, token);
}
最佳答案
这肯定是你遇到的一个错误你可以通过自己构造 HttpContent/ObjectContent 对象来解决它,就像这样。
CancellationTokenSource source = new CancellationTokenSource();
source.Cancel();
HttpClient client = new HttpClient();
var content = new ObjectContent(typeof (MyObject), new MyObject(), new JsonMediaTypeFormatter());
content.LoadIntoBufferAsync().Wait();
try
{
var task = client.PostAsync("http://server-address.com",content, source.Token);
task.Wait();
}
catch (Exception ex)
{
//This will get hit now with an AggregateException containing a TaskCancelledException.
}
调用 content.LoadIntoBufferAsync
强制反序列化发生在 PostAsync 之前,似乎可以避免死锁。
关于c# - 传入一个已经取消的 CancellationToken 导致 HttpClient 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23075255/