В этой статье базы Response.End()
знаний говорится, что ASP.NET прерывает поток.
Отражатель показывает, что это выглядит так:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
Это кажется довольно резким для меня. Как говорится в статье базы знаний, любой следующий код в приложении Response.End()
не будет выполнен, что нарушает принцип наименьшего удивления. Это почти как Application.Exit()
в приложении WinForms. Исключение прерывания потока, вызванное Response.End()
не может быть перехвачено, поэтому окружение кода в try
... finally
не будет удовлетворять.
Это заставляет меня задуматься, стоит ли мне всегда избегать Response.End()
.
Может кто-нибудь предложить, когда я должен использовать Response.End()
, когда Response.Close()
и когда HttpContext.Current.ApplicationInstance.CompleteRequest()
?
ссылка: запись в блоге Рика Строля .
Исходя из полученной информации, мой ответ: да, Response.End
вреден , но полезен в некоторых ограниченных случаях.
- использовать
Response.End()
в качестве неуловимого броска, чтобы немедленно прекратить действиеHttpResponse
в исключительных условиях. Может быть полезно и во время отладки. ИзбегайтеResponse.End()
завершения рутинных ответов . - используйте,
Response.Close()
чтобы немедленно закрыть соединение с клиентом. Согласно этому сообщению в блоге MSDN , этот метод не предназначен для обычной обработки HTTP-запросов. Маловероятно, что у вас будет веская причина для вызова этого метода. - использовать
CompleteRequest()
для завершения обычного запроса.CompleteRequest
заставляет конвейер ASP.NET переходить кEndRequest
событию после завершения текущегоHttpApplication
события. Поэтому, если вы позвонитеCompleteRequest
, то напишите что-нибудь еще в ответ, запись будет отправлена клиенту.
Изменить - 13 апреля 2011
Дополнительная ясность доступна здесь:
- Полезный пост в блоге MSDN
- Полезный анализ Джон Рид
Response.End
ThreadAbortException
просто отлично.Response.Redirect
иServer.Transfer
оба звонкаResponse.End
и следует также избегать.Ответы:
Если вы использовали регистратор исключений в своем приложении, оно будет смягчено с помощью
ThreadAbortException
этих безобидныхResponse.End()
вызовов. Я думаю, что это способ Microsoft сказать "Сбей это!"Я бы использовал, только
Response.End()
если было какое-то исключительное условие и никакие другие действия были невозможны. Может быть, регистрация этого исключения может фактически указывать на предупреждение.источник
TL; DR
За MSDN, Джон Рид и Ален Ренон:
Производительность ASP.NET - управление исключениями - написание кода, исключающего исключения
Решение ThreadAbortException
Response.End и Response.Close не используются в обычной обработке запросов, когда важна производительность. Response.End - это удобное, жесткое средство завершения обработки запроса с соответствующим снижением производительности. Response.Close предназначен для немедленного завершения HTTP-ответа на уровне IIS / сокета и вызывает проблемы с такими вещами, как KeepAlive.
Рекомендуемый метод завершения запроса ASP.NET - HttpApplication.CompleteRequest. Помните, что рендеринг ASP.NET придется пропустить вручную, поскольку HttpApplication.CompleteRequest пропускает остальную часть конвейера приложения IIS / ASP.NET, а не конвейер ASP.NET Page (который является одним из этапов конвейера приложения).
Код
Copyright © 2001-2007, C6 Software, Inc, насколько я мог судить.
Ссылка
HttpApplication.CompleteRequest
Response.End
Response.Close
источник
Этот вопрос появляется в верхней части всех запросов Google по поиску информации на response.end, поэтому для других поисковых запросов, таких как я, которые хотят публиковать CSV / XML / PDF и т. Д. В ответ на событие, не отображая всю страницу ASPX, я так и делаю , (переопределение методов рендеринга слишком сложно для такой простой задачи IMO)
источник
На вопрос «Я до сих пор не знаю разницы между Response.Close и CompleteRequest ()», я бы сказал:
Предпочитаю CompleteRequest (), не используйте Response.Close ().
См. Следующую статью для хорошо сделанного резюме этого случая.
Имейте в виду, что даже после вызова CompleteRequest () некоторый текст (например, выделенный из кода ASPX) будет добавлен к потоку вывода ответа. Вы можете предотвратить это, переопределив методы Render и RaisePostBackEvent, как описано в следующей статье .
Кстати: я согласен с запретом использования Response.End (), особенно при записи данных в поток http для эмуляции загрузки файла. Мы использовали Response.End () в прошлом, пока наш файл журнала не заполнился исключениями ThreadAbortExceptions.
источник
Я не согласен с утверждением « Ответ. И это вредно ». Это определенно не вредно. Response.End делает то, что говорит; это заканчивает выполнение страницы. Использование отражателя, чтобы увидеть, как это было реализовано, следует рассматривать только как поучительный.
Моя 2cent Рекомендации
ИЗБЕЖАТЬ с использованием в
Response.End()
качестве потока управления.СЛЕДУЕТ использовать,
Response.End()
если вам нужно остановить выполнение запроса, и помните, что (как правило) * ни один код не будет выполняться после этой точки.*
Response.End()
и ThreadAbortException s.Response.End()
генерирует исключение ThreadAbortException как часть его текущей реализации (как отмечено OP).Чтобы узнать, как написать код, который должен иметь дело с ThreadAbortExceptions, смотрите ответ @ Mehrdad на SO. Как я могу обнаружить threadabortexception в блоке finally, где он ссылается на метод RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup и Области ограниченного выполнения
Упомянутая статья Рика Строля поучительна, и обязательно прочитайте комментарии. Обратите внимание, что проблема Strahl была конкретной. Он хотел передать данные клиенту (изображение), а затем обработать обновление базы данных отслеживания обращений, которое не замедляло обслуживание изображения, что создавало проблему для выполнения чего-либо после вызова Response.End.
источник
Я никогда не думал об использовании Response.End () для управления потоком программ.
Однако Response.End () может быть полезен, например, при передаче файлов пользователю.
Вы записали файл в ответ и не хотите, чтобы к ответу добавлялось что-либо еще, так как это может повредить ваш файл.
источник
Я использовал Response.End () как в .NET, так и в Classic ASP для принудительного прекращения работы. Например, я использую его, когда есть определенное количество попыток входа в систему. Или когда защищенная страница принимается от неаутентифицированного входа в систему (грубый пример):
При передаче файлов пользователю, который я бы использовал Flush, конец может вызвать проблемы.
источник
Я использовал только Response.End () в качестве механизма тестирования / отладки.
Судя по тому, что вы опубликовали с точки зрения исследований, я бы сказал, что это будет плохой дизайн, если он потребует ответа.
источник
На классическом asp у меня был TTFB (время до первого байта) от 3 до 10 секунд на некоторых вызовах ajax, намного больше, чем TTFB на обычных страницах с большим количеством вызовов SQL.
Возвращенный ajax был сегментом HTML, который нужно вставить на страницу.
TTFB был на несколько секунд длиннее, чем время рендеринга.
Если я добавлю response.end после рендера, TTFB будет значительно уменьшен.
Я мог бы получить тот же эффект, выдав «</ body> </ html>», но это, вероятно, не работает при выводе json или xml; здесь response.end нужен.
источник