Response.Flush() работает только с Firefox

Я пытаюсь отправить некоторый контент клиенту, прежде чем выполнять долгую работу:

Response.Write("Processing...");
Response.Flush();
System.Threading.Thread.Sleep(5000);
Response.Write("Finish");
Response.End();

В Firefox он работает как положено, но в IE8, Safari и Chrome он ждет, пока весь код не будет обработан, а затем показывает весь текст.

Я попытался отправить лучше сформированный HTML, как показано ниже, но получаю те же результаты:

Response.Write("<html><head><title>test</title></head><body>Processing...</body></html>");
Response.Flush();
System.Threading.Thread.Sleep(5000);
Response.Write("Finish");
Response.End();

Спасибо!

5 ответов

Решение

Проблема, с которой вы сталкиваетесь, заключается в том, что отправляемый вами ответ все еще неполон. Даже если вы сбросите все, что находится в буферах, в браузер, браузер все еще должен дождаться окончания ответа или обработать то, что он получил до сих пор - отсюда и разница между браузерами.

Еще хуже то, что вы можете ожидать того же поведения от некоторых концентраторов промежуточных узлов, брандмауэров и т. Д., Расположенных в Интернете между вашим сервером и браузером.

Суть в том, что если вы хотите убедиться, что браузер что-то делает с вашим потоком данных, вы должны заполнить его Response. End.

Другими словами, если вы хотите сначала отправить некоторые из ваших данных ответа и отложить отправку остальных, вам лучше разбить ответ на два, заполнить первый и загрузить вторую часть отдельно.

Также имейте в виду, что если ваш IIS-сервер сжимает вывод с помощью GZIP, то он, похоже, игнорирует все Response.Flush звонки.

Это включено по умолчанию в IIS7 и в Windows 7.

И, если вы тестируете с Fiddler, обязательно включите режим потоковой передачи, иначе Fiddler будет собирать очищенный HTML и удерживать его до тех пор, пока не будет установлено соединение.

Простой способ решить эту проблему - разместить страницу "Пожалуйста, подождите, обработка" перед фактической страницей, которая выполняет эту работу. Появится сообщение "Пожалуйста, подождите", после чего оно сразу же начнет обработку, используя мета-тег обновления и / или JavaScript для перенаправления на реальную страницу обработки.

Страница "Пожалуйста, подождите":

<html>
<head>
  <meta http-equiv="refresh" content="0;url=process.aspx?option1=value&...." />
  <title>Please Wait, Processing</title>
</head>
<body>
  Processing...
</body>
<script type="text/javascript">
  window.location = "process.aspx?option1=value&....";
</script>
</html>

Заметки:

  1. Использование двух методов, чтобы начать обработку, сделано, чтобы гарантировать, что если браузер не может использовать один, он, вероятно, будет использовать другой метод.
  2. Вам придется заменить URL-адрес обработки и строку запроса, чтобы удовлетворить.
  3. Недостатком этого метода является то, что если пользователь нажмет кнопку "Назад" в браузере, он вернется на страницу "Пожалуйста, подождите" со страницы "Процесс", что означает, что он случайно запустит задание снова. Я оставлю этот вызов для другой темы!

Когда вы вызываете Response.Flush() до того, как ответ завершен (до того, как Content-Length станет известен), среда выполнения ASP.NET генерирует частичный ответ с кодированием по частям. Это зависит от браузера, чтобы решить, как это сделать. В моем тестировании я обнаружил, что браузеры имеют тенденцию отображать изображения (<img> теги), которые включены в частичный ответ. Вы можете попробовать.

Тем не менее, будьте осторожны при отправке </html> слишком рано; браузеры могут игнорировать что-либо за пределами этой точки. Тем не менее, браузеры отображают частичные страницы постоянно, поэтому вы можете начать с начала своей страницы, как обычно.

В случае, если это полезно, я подробно рассмотрю пример этого в своей книге, включая трассировку пакетов, которая точно показывает, что происходит на проводе: сверхбыстрый ASP.NET.

Я думаю, что браузеры получают и используют контент в зависимости от его длины, поэтому вы можете попробовать заполнить 1000 символов или около того. Например:

string myVeryShortMessage = "Обработка...";

Response.Write (myVeryShortMessage.PadRight (1000)); Response.Flush, ();

System.Threading.Thread.Sleep (5000);

Response.Write ("Finish".PadRight (1000)); Response.Flush, ();

Другие вопросы по тегам