定期从Http PostAsync响应内容返回的Task <stream>中读取

时间:2016-08-18 07:03:06

标签: c# http async-await

我有一个应用程序,在将文件发布到服务器之后,服务器会在其响应中定期向客户端应用程序返回有关升级过程的消息。

我曾经拥有类似

的代码
using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse())
{
    using (Stream responseStream = httpResponse.GetResponseStream())
    {
        using (var reader = new StreamReader(stream))
        {
            while(!streamReader.EndOfStream)
            {
                var str = streamReader.ReadLine();
                // Do something with str
            }
        }
    }
}

在更新我的代码以使用HttpClient类之后,我正在努力寻找一种与上面的代码相同的方法。

var response = client.PostAsync(uploadUrl, content).Result;

var stream = response.Content.ReadAsStreamAsync().Result;

var streamReader = new StreamReader(stream);

// Superfluous due to the fact we are already at end of stream
while(!streamReader.EndOfStream)
{
    var str = streamReader.ReadLine();
    // Do something with str
}

如果我尝试类似上面的内容,那么我们会等到整个流已经填充,然后由于使用response.Content.ReadAsStreamAsync().Result调用而一次全部返回。这不适合我希望在从服务器返回时实时显示信息。

当我们有一个Task<Stream>对象时,是否可以定期从流中读取,如上例所示?

1 个答案:

答案 0 :(得分:3)

ReadAsStreamAsync()仅在收到所有内容后才返回的原因是PostAsync()内部使用HttpCompletionOption.ResponseContentRead。你想要的是HttpCompletionOption.ResponseHeadersRead

HttpClient上的某些方法有一个接受HttpCompletionOption的重载,允许您覆盖默认值。不幸的是,PostAsync()没有。显然,这是因为responses to POST requests are not supposed to be long

但是您仍然可以使用常规SendAsync()方法执行您想要的操作:

var response = client.SendAsync(
    new HttpRequestMessage(HttpMethod.Post, uploadUrl) { Content = content },
    HttpCompletionOption.ResponseHeadersRead).Result;