Почему Ответ.Перенаправление вызывает систему.Нарезка резьбы.ThreadAbortException?
когда я использую ответ.Переадресовывать.(..) чтобы перенаправить мою форму на новую страницу, Я получаю сообщение об ошибке:
первый шанс исключение типа 'System.Нарезка резьбы.ThreadAbortException ' произошло в mscorlib.dll
Исключение типа 'System.Нарезка резьбы.ThreadAbortException ' произошло в mscorlib.DLL но не был обработан в пользовательском коде
мое понимание этого заключается в том, что ошибка вызвана тем, что веб-сервер прерывает оставшуюся часть страницы ответ.был вызван редирект.
Я знаю, что я могу добавить второй параметр Response.Redirect Это называется endResponse. Если я установил endResponse в True, я все равно получаю ошибку, но если я установил ее в False, то я этого не делаю. Я уверен, что это означает, что веб-сервер работает остальная часть страницы, с которой я перенаправлен. Что было бы по меньшей мере неэффективно. Есть ли лучший способ сделать это? Что-то другое, чем Response.Redirect или есть способ заставить старую страницу остановиться загрузка, где я не получу ThreadAbortException?
10 ответов:
правильный шаблон должен вызвать перегрузку перенаправления с endResponse=false и сделать вызов, чтобы сообщить конвейеру IIS, что он должен перейти непосредственно к этапу EndRequest после возврата control:
Response.Redirect(url, false); Context.ApplicationInstance.CompleteRequest();этот блог от Thomas Marquardt предоставляет дополнительные сведения, в том числе как обрабатывать особый случай перенаправления внутри обработчика Application_Error.
здесь нет простое и элегантное решение
Redirectпроблема в ASP.Net веб-формы. Вы можете выбрать между грязный решение нудно решениегрязный:
Response.Redirect(url)отправляет перенаправление в браузер, а затем бросаетThreadAbortedExceptionдля завершения текущего потока. Таким образом, код не выполняется после Redirect()-вызова. Недостатки: это плохая практика и имеет последствия для производительности, чтобы убить такие потоки. Кроме того,ThreadAbortedExceptionsпоявится в журнале исключений.нудно: рекомендуемый способ-позвонить
Response.Redirect(url, false)а тоContext.ApplicationInstance.CompleteRequest()тем не менее, выполнение кода будет продолжено, а остальные обработчики событий в жизненном цикле страницы все еще будут выполняться. (Например, если вы выполняете перенаправление в Page_Load, не только будет выполняться остальная часть обработчика, Page_PreRender и т. д. Также будут вызваны - визуализированная страница просто не будет отправлена в браузер. Вы можете избежать дополнительная обработка, например, установив флаг на странице, а затем пусть последующие обработчики событий проверяют этот флаг перед выполнением любой обработки.(документации
CompleteRequestутверждает, что это " причины ASP.NET для обхода всех событий и фильтрации в цепочке выполнения HTTP конвейера". Это может быть легко неправильно понято. Он обходит дальнейшие HTTP-фильтры и модули, но он не обходит дальнейшие события в текущем страница жизненный цикл.)более глубокая проблема заключается в том, что WebForms не хватает уровня абстракции. Когда вы находитесь в обработчике событий, вы уже находитесь в процессе создания страницы для вывода. Перенаправление в обработчике событий является уродливым, потому что вы завершаете частично сгенерированную страницу, чтобы создать другую страницу. MVC не имеет этой проблемы, так как поток управления отделен от представлений рендеринга, поэтому вы можете сделать чистый редирект, просто вернув
RedirectActionв контроллере, без создания представления.
Я знаю, что опоздал, но у меня только когда-либо была эта ошибка, если мой
Response.Redirectнаходится вTry...Catchблок.никогда не ставьте ответ.Перенаправление в попытку...Блок catch. Это плохая практика
Edit
в ответ на комментарий @Kiquenet, вот что я хотел бы сделать в качестве альтернативы положить ответ.Перенаправление в попытку...Блок catch.
Я бы разбил метод / функцию на два шага.
Шаг первый внутри попытки...Блок catch выполняет запрошенные действия и устанавливает значение "результат", чтобы указать успех или неудачу действий.
Шаг второй за пределами попытки...Блок Catch выполняет перенаправление (или нет) в зависимости от значения "результат".
этот код далек от совершенства и, вероятно, не следует копировать, так как я не проверял его
public void btnLogin_Click(UserLoginViewModel model) { bool ValidLogin = false; // this is our "result value" try { using (Context Db = new Context) { User User = new User(); if (String.IsNullOrEmpty(model.EmailAddress)) ValidLogin = false; // no email address was entered else User = Db.FirstOrDefault(x => x.EmailAddress == model.EmailAddress); if (User != null && User.PasswordHash == Hashing.CreateHash(model.Password)) ValidLogin = true; // login succeeded } } catch (Exception ex) { throw ex; // something went wrong so throw an error } if (ValidLogin) { GenerateCookie(User); Response.Redirect("~/Members/Default.aspx"); } else { // do something to indicate that the login failed. } }
Response.Redirect()исключение для прерывания текущего запроса.этой статьи описывает это поведение (также для
Request.End()иServer.Transfer()методов).на
Response.Redirect()существует перегрузка:Response.Redirect(String url, bool endResponse)если вы передадите endResponse=false, то исключение не выбрасывается (но среда выполнения продолжит обработку текущего запроса).
если endResponse=true (или если другая перегрузка используется), исключение и текущий запрос будет немедленно удалена.
Это просто как ответ.Редирект (url, true) работает. Он выбрасывает исключение ThreadAbortException, чтобы прервать поток. Просто игнорируйте это исключение. (Я предполагаю, что это какой-то глобальный обработчик ошибок/регистратор, где вы его видите?)
интересные обзоры обсуждение - Это Ответ.Конец () считается вредным?
здесь официальный строку по проблеме (я не смог найти последнюю, но я не думаю, что ситуация изменилась для более поздних версий .net)
Я даже пытался избежать этого, на всякий случай делая прерывание в потоке вручную, но я скорее оставляю его с "CompleteRequest" и двигаюсь дальше - мой код имеет команды возврата после перенаправления в любом случае. Так что это можно сделать
public static void Redirect(string VPathRedirect, global::System.Web.UI.Page Sender) { Sender.Response.Redirect(VPathRedirect, false); global::System.Web.UI.HttpContext.Current.ApplicationInstance.CompleteRequest(); }
то, что я делаю, это поймать это исключение, вместе с другими возможными исключениями. Надеюсь, это поможет кому-то.
catch (ThreadAbortException ex1) { // do nothing } catch(Exception ex) { writeToLog(ex.Message); }
также я пробовал другое решение, но некоторые из кода, выполненного после перенаправления.
public static void ResponseRedirect(HttpResponse iResponse, string iUrl) { ResponseRedirect(iResponse, iUrl, HttpContext.Current); } public static void ResponseRedirect(HttpResponse iResponse, string iUrl, HttpContext iContext) { iResponse.Redirect(iUrl, false); iContext.ApplicationInstance.CompleteRequest(); iResponse.BufferOutput = true; iResponse.Flush(); iResponse.Close(); }Так что если нужно предотвратить выполнение кода после переадресации
try { //other code Response.Redirect("") // code not to be executed } catch(ThreadAbortException){}//do there id nothing here catch(Exception ex) { //Logging }
У меня тоже была такая проблема. Попробуйте использовать сервер.Передача вместо ответа.Перенаправлять Работал на меня
Comments