取消HttpClient'POST请求

本文关键字:POST 请求 HttpClient 取消 | 更新日期: 2023-09-27 18:03:23

我正在我的Windows Phone 8应用程序上上传HttpClient.PostAsync()的图像。用户可以选择通过UI按钮取消此上传。

为了取消POST请求,我设置了一个CancellationToken。但这行不通。在取消请求之后,我仍然看到我的代理中正在进行上传,很明显请求被忽略了。我的代码:

using (var content = new MultipartFormDataContent())
{
    var file = new StreamContent(stream);
    file .Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
    {
        FileName =  "filename.jpg",
    };
    file.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
    content.Add(file);
    await httpclient.PostAsync(new Uri("myurl", UriKind.Absolute), content,
        cancellationToken);
}

还请注意,我有一个CancellationTokenSourceCancellationToken。用户单击Cancel按钮后,调用tokensource.Cancel()。另外,我的测试用例中的图像大小从1到2 MB(不是那么大)。

所以,有没有办法取消HttpClient POST请求?

取消HttpClient'POST请求

try
{
    var client = new HttpClient();
    var cts = new CancellationTokenSource();
    cts.CancelAfter(3000); // 3 seconds
    var request = new HttpRequestMessage();
    await client.PostAsync(url, content, cts.Token);
}
catch(OperationCanceledException ex)
{
    // timeout has been hit
}

取消任务不会立即终止任务。您必须在执行工作之前手动检查令牌的状态:

if (ct.IsCancellationRequested) 
{
    ct.ThrowIfCancellationRequested();
}
// Post request here...

这篇文章非常有用:如何:取消任务及其子任务

在像Xamarin这样的Mono的HttpClient实现中,get &如果主机不可达,则post方法不执行取消令牌,并在失败之前等待最多2分钟。这可能就是为什么带有CancelAfter的CancellationTokenSource在这里不起作用的原因。

要解决这个问题,我发现最简单的方法是使用Polly库https://github.com/App-vNext/Polly
var policy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(3000),
    TimeoutStrategy.Pessimistic,
    (context, timespan, task) => throw new Exception("Cannot connect to server."));
await policy.ExecuteAsync(async () =>
{
    var httpClient = new HttpClient();
    var response = await httpClient.PostAsync(...);
    response.EnsureSuccessStatusCode();
    ...
});