ASP.NET Web API:PushStreamContent flush不会刷新

时间:2015-04-22 09:32:01

标签: c# asp.net-web-api server-sent-events pushstreamcontent

我在ASP.NET Web API中使用PushStreamContent将事件从服务器推送到客户端(使用服务器发送的事件)。在每次发送事件后,我在Flush上调用Stream将缓冲的数据推送到客户端。但是,我注意到冲洗不会(总是)发生。有时,部分数据被发送到客户端,其余部分在下一个事件被写入时发送(可能在几秒钟后发生)。

这是一个代码示例:

public class MyController : ApiController
{
  private static readonly string[] LineSeparators 
    = new[] { Environment.NewLine };

  public HttpResponseMessage GetData(string id)
  {
    var response = Request.CreateResponse();
    response.Content = new PushStreamContent(
      new Func<Stream, HttpContent, TransportContext, Task>(StartStream),
      new MediaTypeHeaderValue("text/event-stream") { CharSet = "UTF-8" });
    return response;
  }

  private async Task StartStream(Stream outputStream, HttpContent content, TransportContext context)
  {
    using (outputStream)
    using (var writer = new StreamWriter(outputStream, new UTF8Encoding(false)))
    {
      writer.NewLine = "\n";
      while (true)
      {
        WriteEvent(writer, "ping", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
        await Task.Delay(TimeSpan.FromSeconds(1));
      }
    }
  }

  private static void WriteEvent(TextWriter writer, string eventType, string data)
  {
    writer.WriteLine("event:" + eventType);
    writer.WriteLine("data:" + data);
    writer.WriteLine();
    writer.Flush(); // StreamWriter.Flush calls Flush on underlying Stream
  }
}

如何禁用数据缓冲或强制刷新数据?

3 个答案:

答案 0 :(得分:2)

我明白了。

在我的案例中,缓冲是一个问题。我不得不

1)为我的回复<urlCompression doStaticCompression="true" doDynamicCompression="false" />

停用gzip

2)确保Prod(Nginx)上的代理没有缓冲

答案 1 :(得分:1)

问题的根源是Stream被刷新。

在您的代码示例中,您使用StreamWriter扭曲原始流,然后刷新StreamWriter。

您还需要刷新原始流:

private async Task StartStream(Stream outputStream, HttpContent content, TransportContext context)
{
  using (outputStream)
  using (var writer = new StreamWriter(outputStream, new UTF8Encoding(false)))
  {
    writer.NewLine = "\n";
    while (true)
    {
      WriteEvent(writer, "ping", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
outputStream.Flush();
      await Task.Delay(TimeSpan.FromSeconds(1));
    }
  }
}

答案 2 :(得分:1)

花了整整一天的时间来弄清楚问题出在哪里,并竭尽全力地(赏心悦目)给出赏金后,我发现问题在于我正在使用HttpSelfHostServer ,并且需要在TransferMode = TransferMode.Streamed上配置HttpSelfHostConfiguration。就是这样。