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>
Заметки:
- Использование двух методов, чтобы начать обработку, сделано, чтобы гарантировать, что если браузер не может использовать один, он, вероятно, будет использовать другой метод.
- Вам придется заменить URL-адрес обработки и строку запроса, чтобы удовлетворить.
- Недостатком этого метода является то, что если пользователь нажмет кнопку "Назад" в браузере, он вернется на страницу "Пожалуйста, подождите" со страницы "Процесс", что означает, что он случайно запустит задание снова. Я оставлю этот вызов для другой темы!
Когда вы вызываете 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, ();