Почему Ответ.Перенаправление вызывает систему.Нарезка резьбы.ThreadAbortException?



когда я использую ответ.Переадресовывать.(..) чтобы перенаправить мою форму на новую страницу, Я получаю сообщение об ошибке:




первый шанс исключение типа 'System.Нарезка резьбы.ThreadAbortException ' произошло в mscorlib.dll

Исключение типа 'System.Нарезка резьбы.ThreadAbortException ' произошло в mscorlib.DLL но не был обработан в пользовательском коде




мое понимание этого заключается в том, что ошибка вызвана тем, что веб-сервер прерывает оставшуюся часть страницы ответ.был вызван редирект.



Я знаю, что я могу добавить второй параметр Response.Redirect Это называется endResponse. Если я установил endResponse в True, я все равно получаю ошибку, но если я установил ее в False, то я этого не делаю. Я уверен, что это означает, что веб-сервер работает остальная часть страницы, с которой я перенаправлен. Что было бы по меньшей мере неэффективно. Есть ли лучший способ сделать это? Что-то другое, чем Response.Redirect или есть способ заставить старую страницу остановиться загрузка, где я не получу ThreadAbortException?

587   10  

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

    Ничего не найдено.