I am wanting to use a CancellationToken
to cancel a call to HttpClient.PostAsJsonAsync
. However, with the following setup the call to PostAsJsonAsync
hangs indefinitely (I left it running for several minutes).
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.
}
Note that I am passing an already cancelled CancellationTokenSource
- I have the same problem if I cancel the token using Task.Delay
with a short delay.
I realise I could simply check whether the token has been cancelled prior to the call, but even so, I have the same problem if the token gets cancelled after a short delay, i.e., it's not cancelled before the method call but becomes so shortly after it.
So my question is, what is causing this and what can I do to work around/fix it?
Edit
For those looking for a workaround, inspired by @Darrel Miller's answer, I came up with the following extension method:
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);
}
It definitely seems to be a bug that you hit You can work around it by constructing the HttpContent/ObjectContent object yourself, like this.
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.
}
Calling the content.LoadIntoBufferAsync
forces the deserialization to happen before the PostAsync and seems to avoid the deadlock.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With