HttpClient在using语句中导致Task被取消 [英] HttpClient in using statement causes Task cancelled

查看:350
本文介绍了HttpClient在using语句中导致Task被取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为我的api调用创建了FileResult : IHttpActionResult webapi返回类型. FileResult从另一个URL下载文件,然后将流返回给客户端.

I created a FileResult : IHttpActionResult webapi return type for my api calls. The FileResult downloads a file from another url and then returns the stream to the client.

最初,我的代码具有using语句,如下所示:

Initially my code had a using statement like below:

public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
    try
    {
        HttpResponseMessage response;
        using (var httpClient = new HttpClient())
        {

            response = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new System.Net.Http.StreamContent(
                                    await httpClient.GetStreamAsync(this.filePath))
            };
        }
        return response;
    }
    catch (WebException exception)
    {...}
}

但是,这会间歇性地导致TaskCanceledException.我知道,如果在异步调用完成之前处理HttpClient,则Task的状态将更改为Canceled.但是,由于我在Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath))中使用了 await ,因此应防止HttpClient在任务完成过程中被丢弃.

However this would intermittently cause a TaskCanceledException. I know that if the HttpClient is disposed before the asychronous call is finished the Task's state will change to canceled. However since I use an await in: Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath)) that should prevent the HttpClient from being disposed off in the middle of the task completion.

为什么该任务被取消?不是因为超时,因为它发生在最小的请求上,而并不总是发生在大请求上.

Why does that task get canceled? It is not because of a timeout since this has happened on the smallest requests and doesn't always occur on large requests.

当我删除using语句时,代码可以正常工作:

When I removed the using statement the code worked properly:

public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
    try
    {
        HttpResponseMessage response;
        var httpClient = new HttpClient();

        response = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new System.Net.Http.StreamContent(
                                await httpClient.GetStreamAsync(this.filePath))
        };
        return response;
    }
    catch (WebException exception)
    {...}
}

您知道为什么使用会导致此问题吗?

Any idea why the using caused the issue?

推荐答案

我知道,如果HttpClient在异步调用完成之前被处理掉,则Task的状态将更改为Canceled.但是,由于我在以下环境中使用await:Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath)),应防止HttpClient在任务完成过程中被丢弃.

I know that if the HttpClient is disposed before the asychronous call is finished the Task's state will change to canceled. However since I use an await in: Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath)) that should prevent the HttpClient from being disposed off in the middle of the task completion.

但是该任务做什么?它获得流.因此,您的代码最终以Stream结尾,当它关闭HttpClient时,它可能会完全读取,也可能不会完全读取.

But what does that task do? It gets the stream. So, your code ends up with a Stream that may or may not be completely read when it closes the HttpClient.

HttpClient是专门为重用(和同时使用)设计的,因此,我建议完全删除using并将HttpClient声明移到static类成员.但是,如果要关闭并重新打开客户端,则应该通过在关闭HttpClient之前将流完全读入内存中来使它正常工作.

HttpClient is specifically designed for reuse (and simultaneous use), so I recommend removing the using completely and moving the HttpClient declaration to a static class member. But if you want to close and reopen the clients, you should be able to get it working by reading the stream entirely into memory before closing the HttpClient.

这篇关于HttpClient在using语句中导致Task被取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆