HttpContent.ReadAsStringAsync导致请求挂起(或其他奇怪行为) [英] HttpContent.ReadAsStringAsync causes request to hang (or other strange behaviours)

查看:2190
本文介绍了HttpContent.ReadAsStringAsync导致请求挂起(或其他奇怪行为)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在建设一个高度并行的Web应用程序,而且最近我们已经使用异步编程广泛开始(使用TPL和异步 / 等待)。



我们有一个分布式环境中哪些应用程序之间通过REST API的(在建的ASP.NET Web API之上)进行通信。在一个特定的应用程序,我们有一个 DelegatingHandler 在调用后 base.SendAsync (即计算响应后)日志响应于一个文件中。我们有响应的日志中的基本信息(状态码,标题和内容):



<预类=郎-CS prettyprint-覆盖> 公开静态字符串SerializeResponse(HttpResponseMessage响应)
{
变种建设者=新的StringBuilder();
无功含量= ReadContentAsString(response.Content);

builder.AppendFormat(HTTP / {0} {1:D} {1},response.Version.ToString(2),response.StatusCode);
builder.AppendLine();
builder.Append(response.Headers); (!string.IsNullOrWhiteSpace(内容))

如果
{
builder.Append(response.Content.Headers);

builder.AppendLine();
builder.AppendLine(美化(内容));
}

返回builder.ToString();
}

私人静态字符串ReadContentAsString(HttpContent内容)
{
返回内容== NULL?空:content.ReadAsStringAsync()结果。
}



问题是这样的:当代码达到内容.ReadAsStringAsync()。结果沉重的服务器负载下,请求有时挂在IIS。当它,它有时会返回一个响应 - 但挂在IIS,如果它没有 - 或者在其他时候,它永远不会返回



我也尝试阅读使用 ReadAsByteArrayAsync 的内容,然后将其转换为字符串,没有运气。



当我转换为使用异步贯穿我得到更加古怪的结果代码:



<预类=郎-CS prettyprint-覆盖> 公共静态异步任务<串GT; SerializeResponseAsync(HttpResponseMessage响应)
{
变种建设者=新的StringBuilder();
VAR内容=等待ReadContentAsStringAsync(response.Content);

builder.AppendFormat(HTTP / {0} {1:D} {1},response.Version.ToString(2),response.StatusCode);
builder.AppendLine();
builder.Append(response.Headers); (!string.IsNullOrWhiteSpace(内容))

如果
{
builder.Append(response.Content.Headers);

builder.AppendLine();
builder.AppendLine(美化(内容));
}

返回builder.ToString();
}

私有静态任务<串GT; ReadContentAsStringAsync(HttpContent内容)
{
返回内容== NULL? Task.FromResult<串GT;(空):content.ReadAsStringAsync();
}

现在 HttpContext.Current 是调用 content.ReadAsStringAsync后空()它不断被空所有后续请求!我知道这听起来令人难以置信的 - 我花了一些时间和三个同事在场接受,这是真的发生了。



这是某种预期的行为?难道我做错了吗?


解决方案

我有这个问题。虽然,我还没有完全测试过,用CopyToAsync代替ReadAsStringAsync似乎来解决这个问题:

  VAR毫秒=新的MemoryStream (); 
等待response.Content.CopyToAsync(毫秒);
ms.Seek(0,SeekOrigin.Begin);

变种SR =新的StreamReader(毫秒);
responseContent = sr.ReadToEnd();


We are building a highly concurrent web application, and recently we have started using asynchronous programming extensively (using TPL and async/await).

We have a distributed environment, in which apps communicate with each other through REST APIs (built on top of ASP.NET Web API). In one specific app, we have a DelegatingHandler that after calling base.SendAsync (i.e., after calculating the response) logs the response to a file. We include the response's basic information in the log (status code, headers and content):

public static string SerializeResponse(HttpResponseMessage response)
{
    var builder = new StringBuilder();
    var content = ReadContentAsString(response.Content);

    builder.AppendFormat("HTTP/{0} {1:d} {1}", response.Version.ToString(2), response.StatusCode);
    builder.AppendLine();
    builder.Append(response.Headers);

    if (!string.IsNullOrWhiteSpace(content))
    {
        builder.Append(response.Content.Headers);

        builder.AppendLine();
        builder.AppendLine(Beautified(content));
    }

    return builder.ToString();
}

private static string ReadContentAsString(HttpContent content)
{
    return content == null ? null : content.ReadAsStringAsync().Result;
}

The problem is this: when the code reaches content.ReadAsStringAsync().Result under heavy server load, the request sometimes hangs on IIS. When it does, it sometimes returns a response -- but hangs on IIS as if it didn't -- or in other times it never returns.

I have also tried reading the content using ReadAsByteArrayAsync and then converting it to String, with no luck.

When I convert the code to use async throughout I get even weirder results:

public static async Task<string> SerializeResponseAsync(HttpResponseMessage response)
{
    var builder = new StringBuilder();
    var content = await ReadContentAsStringAsync(response.Content);

    builder.AppendFormat("HTTP/{0} {1:d} {1}", response.Version.ToString(2), response.StatusCode);
    builder.AppendLine();
    builder.Append(response.Headers);

    if (!string.IsNullOrWhiteSpace(content))
    {
        builder.Append(response.Content.Headers);

        builder.AppendLine();
        builder.AppendLine(Beautified(content));
    }

    return builder.ToString();
}

private static Task<string> ReadContentAsStringAsync(HttpContent content)
{
    return content == null ? Task.FromResult<string>(null) : content.ReadAsStringAsync();
}

Now HttpContext.Current is null after the call to content.ReadAsStringAsync(), and it keeps being null for all the subsequent requests! I know this sounds unbelievable -- and it took me some time and the presence of three coworkers to accept that this was really happening.

Is this some kind of expected behavior? Am I doing something wrong here?

解决方案

I had this problem. Although, I haven't fully tested yet, using CopyToAsync instead of ReadAsStringAsync seems to fix the problem:

var ms = new MemoryStream();
await response.Content.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);

var sr = new StreamReader(ms);
responseContent = sr.ReadToEnd();

这篇关于HttpContent.ReadAsStringAsync导致请求挂起(或其他奇怪行为)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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