Какой хороший общий способ отловить исключение StackOverflow в C #? - PullRequest
4 голосов
/ 06 октября 2010

Если у меня есть метод, который, как я знаю, мог бы потенциально повторяться бесконечно, но я не могу с уверенностью предсказать, какие условия / параметры вызвали бы его, какой хороший способ в C # сделать это:

try
{
  PotentiallyInfiniteRecursiveMethod();
}
catch (StackOverflowException)
{
  // Handle gracefully.
}

Очевидно, что в главном потоке вы не можете этого сделать, но мне несколько раз говорили, что это можно сделать с помощью потоков или домена приложений, но я никогда не видел работающего примера. Кто-нибудь знает, как это сделать надежно?

Ответы [ 2 ]

11 голосов
/ 06 октября 2010

Вы не можете. От MSDN

Начиная с .NET Framework версия 2.0, исключение StackOverflowException объект не может быть пойман при помощи try-catch блок и соответствующий процесс прекращено по умолчанию. Как следствие, пользователям рекомендуется написать свой код обнаружить и предотвратить стек переполнение. Например, если ваш применение зависит от рекурсии, использования счетчик или состояние состояния завершить рекурсивный цикл. Заметка что приложение, которое размещает общеязыковая среда выполнения (CLR) может указать, что CLR выгрузить домен приложения, где находится стек возникает исключение переполнения, и пусть соответствующий процесс продолжается. За больше информации, см. Интерфейс ICLRPolicyManager и Обзор хостинга.

1 голос
/ 06 октября 2010

Нет способа поймать StackOverflowException, но вы можете сделать что-то с необработанным исключением:

static void Main()
{
AppDomain.CurrentDomain.UnhandledException += 
  new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}

static void CurrentDomain_UnhandledException
  (object sender, UnhandledExceptionEventArgs e)
{
  try
  {
    Exception ex = (Exception)e.ExceptionObject;

    MessageBox.Show("Whoops! Please contact the developers with the following" 
          + " information:\n\n" + ex.Message + ex.StackTrace, 
          "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
  }
  finally
  {
    Application.Exit();
  }
}
...