System.Threading.ThreadAbortException, вызванный Response.Redirect - PullRequest
4 голосов
/ 01 апреля 2012

В моем приложении я вызываю WebMethod из JavaScript, где я пытаюсь перенаправить на какую-то страницу:

[WebMethod]
public string Logout() {            
    if (User.Identity.IsAuthenticated) {                            
        HttpContext.Current.Response.Redirect("~/Pages/Logout.aspx");               
    }
    return "";
}

Страница aspx:

    <input onclick="callLogout();" id="btn" type="button" value="Click Me" />

    <asp:ScriptManager ID="ScriptManager" runat="server">
        <Services>
            <asp:ServiceReference Path="~/WebServices/EMSWebService.asmx" />
        </Services>
    </asp:ScriptManager>
    <script type="text/javascript">        
        function callLogout() {
            EMSApplication.Web.WebServices.EMSWebService.Logout(OnComplete, OnError);
        }

        function OnComplete(result) {
            alert(result);
        }

        function OnError(result) {
            alert(result.get_message());
        }
    </script>

И я получаю:

Первое случайное исключение типа 'System.Threading.ThreadAbortException' произошло в mscorlib.dll

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

в окне вывода моего VS2010.

Почему я получаю это исключение и как я могу его устранить?

Ответы [ 3 ]

9 голосов
/ 27 июня 2012

Идеальный способ перенаправления - позвонить Response.Redirect(someUrl, false), а затем позвонить CompleteRequest()

Передача false в Response.Redirect(...) предотвратит повышение ThreadAbortException, однако по-прежнему важно завершить жизненный цикл страницы, вызвав CompleteRequest().

Когда вы используете этот метод в обработчике страницы для завершения запроса одну страницу и начать новый запрос для другой страницы, установите endResponse в false и затем вызывают метод CompleteRequest () . Если вы укажете истину для параметра endResponse этот метод вызывает метод End для исходный запрос, который генерирует исключение ThreadAbortException когда это завершится. Это исключение имеет пагубное влияние на сеть производительность приложения, поэтому передает false для Параметр endResponse рекомендуется . Для получения дополнительной информации см. Завершить метод.

Обратите внимание, что при вызове метода Response.Redirect(...) создается новый поток с новым жизненным циклом страницы для обработки нового перенаправленного ответа. Когда новый ответ заканчивается, он вызывает Response.End() в исходном ответе, который в конечном итоге выдает ThreadAbortException и вызывает событие EndRequest. Если вы препятствуете вызову Response.End() (путем передачи false на Response.Redirect), тогда вам нужно позвонить CompleteRequest(), который:

Заставляет ASP.NET обходить все события и фильтрацию в конвейере HTTP. цепочка выполнения и непосредственно выполнить событие EndRequest.

Слово предостережения:

Если вы позвоните по номеру Response.Redirect(someUrl, false), позволяющему продолжить выполнение кода, вы можете изменить свой код так, чтобы обработка корректно прекратилась. Иногда это так же просто, как добавить return к вызову метода void. Однако, если вы находитесь в глубоком стеке вызовов, это намного сложнее, и если вы не хотите, чтобы больше кода выполнялось, было бы легче передать true, как Response.Redirect(someUrl, true), и преднамеренно ожидать ThreadAbortException - что, кстати, не является ' Плохая вещь, вы должны ожидать этого во время Response.Redirect(...) и Server.Transfer(...) звонков.

ThreadAbortException не может быть остановлено путем перехвата исключения

ThreadAbortException не является вашим обычным исключением. Даже если вы поместите свой код в блок try catch, исключение ThreadAbortException сразу же будет вызвано после предложения finally.

Когда вызывается метод Abort для уничтожения потока, общеязыковая среда выполнения выдает исключение ThreadAbortException. ThreadAbortException - это особое исключение, которое может быть перехвачено, но оно автоматически поднимется снова в конце блока захвата . когда это исключение возникает, среда выполнения выполняет все блоки finally до окончания потока. Потому что поток может делать неограниченное вычисление в блоках finally или вызов Thread.ResetAbort для отмены прерывание , нет никакой гарантии, что поток когда-либо закончится. если ты хотите дождаться окончания прерванного потока, вы можете вызвать Thread.Join метод. Присоединение - это блокирующий вызов, который не возвращается до поток фактически останавливается.

Часто в коде я видел блок try catch для Response.Redirect, который будет регистрировать исключения, которые не являются ThreadAbortExceptions (так как вы ожидаете их). Пример: * 1 059 *

private void SomeMethod()
{
   try
   {
      // Do some logic stuff
      ...

      if (someCondition)
      {
         Response.Redirect("ThatOneUrl.aspx", true);
      }
   }
   catch (ThreadAbortException)
   {
      // Do nothing.  
      // No need to log exception when we expect ThreadAbortException
   }
   catch (Exception ex)
   {
      // Looks like something blew up, so we want to record it.
      someLogger.Log(ex);
   }
}
0 голосов
/ 01 апреля 2012

Не просто поймать исключение.Используйте перегрузку Redirect, которая принимает логическое значение.Передайте false, чтобы указать, что вы не хотите прерывать поток.

0 голосов
/ 01 апреля 2012

Это стандартное исключение, вызванное Response.Redirect, перехваченным, только если у вас есть явный try-catch над блоком, который выполняет перенаправление. ASP.NET выдает его при перенаправлении, поэтому после перенаправления код не выполняется.

Решение состоит в том, чтобы добавить пустой улов, чтобы проглотить это конкретное исключение

try {
   ...
   Response.Redirect( ... );
}
catch ( ThreadAbortException ) { } // swallow the exception
catch ( Exception ex ) { 
   // an existing catch clause
}
...