Веб-API ASP.NET: сбрасывание PushStreamContent не выполняется

Я использую PushStreamContent в ASP.NET Web API для передачи событий с сервера на клиент (используя события, отправленные сервером). После каждого отправленного события я звоню 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
  }
}

Как я могу отключить буферизацию данных или принудительно сбросить данные?

2 ответа

Я получил это работает.

В моем случае буферизация была проблемой. Мне пришлось

1) отключить gzip для моих ответов <urlCompression doStaticCompression="true" doDynamicCompression="false" />

2) Убедитесь, что прокси на Prod (Nginx) тоже не буферизуется

Потратив целый день на то, чтобы выяснить, в чем проблема, и зайти так далеко (отчаянно), чтобы получить награду, я обнаружил, что проблема заключается в том, что я использовал HttpSelfHostServerи нужно было настроить TransferMode = TransferMode.Streamed на HttpSelfHostConfiguration, Это все.

Источником проблемы является сбрасываемый поток.

В своем примере кода вы деформируете исходный поток с помощью 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));
    }
  }
}
Другие вопросы по тегам