Когда попытка поймать, а не попытка? - PullRequest
5 голосов
/ 18 апреля 2010

У меня забавная проблема, когда во время закрытия приложения блоки try / catch в стеке, похоже, игнорируются.

У меня нет работающего тестового проекта (но из-за крайнего срока, в противном случае я бы полностью попытался повторить это), но рассмотрим следующий фрагмент кода.

class IndexNotFoundException : Exception { }

public static string RunAndPossiblyThrow(int index, bool doThrow)
{
    try
    {
        return Run(index);
    }
    catch(IndexNotFoundException e)
    {
         if(doThrow)
             throw;
    }
    return "";
}

public static string Run(int index)
{
    if(_store.Contains(index))
        return _store[index];
    throw new IndexNotFoundException ();
}

public static string RunAndIgnoreThrow(int index)
{
    try
    {
        return Run(index);
    }
    catch(IndexNotFoundException e)
    {
    }
    return "";
}

Во время выполнения этот шаблон отлично работает. Мы получаем унаследованную поддержку кода, который использует исключения для управления программой (плохо), и мы можем двигаться вперед и медленно удалять исключения, используемые для управления программой.

Однако при закрытии нашего пользовательского интерфейса мы видим исключение, выдаваемое из «Run», даже если «doThrow» имеет значение false для ВСЕХ текущих применений «RunAndPossblyThrow». Я даже зашел так далеко, чтобы проверить это, изменив код так, чтобы он выглядел как «RunAndIgnoreThrow», и я все равно получу аварийное завершение работы после отключения пользовательского интерфейса.

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

EDIT Это многопоточный, и я убедился, что все объекты не были изменены при доступе

EDIT Явное шоу исключение наше

EDIT забыл упомянуть, это на закрытии, и, к сожалению, Visual Studio не может поймать падение непосредственно. Скорее всего, происходит сбой в потоке, отличном от потока пользовательского интерфейса, и после закрытия основного происходит закрытие. Я смог отладить это только путем многократного запуска и закрытия приложения с открытым диспетчером задач «Создать файл дампа» и просмотром полученного беспорядка в 400+ мегабайт в Windbg. Win7 64 для справки. Убедитесь, что это имеет смысл для вас.

EDIT

Следующий код при завершении работы по-прежнему показывает то же исключение.

class IndexNotFoundException : Exception { }

public static string RunAndPossiblyThrow(int index, bool doThrow)
{
    try
    {
        return Run(index);
    }
    catch
    {
    }
    return "";
}

public static string Run(int index)
{
    if(_store.Contains(index))
        return _store[index];
    throw new IndexNotFoundException ();
}

Единственное, что, кажется, избавляется от исключения, - это перейти прямо к

class IndexNotFoundException : Exception { }

public static string RunAndPossiblyThrow(int index, bool doThrow)
{
    try
    {
        return Run(index);
    }
    catch
    {
    }
    return "";
}

public static string Run(int index)
{
    if(_store.Contains(index))
        return _store[index];
    return "";
}

Естественно, исключение прошло, но мои страхи сойти с ума все еще присутствуют.

EDIT

стало еще хуже ... это все еще падает ...

class IndexNotFoundException : Exception { }

public static string RunAndPossiblyThrow(int index, bool doThrow)
{
    try
    {
        throw new IndexNotFoundException();
    }
    catch
    {
    }
    return "";
}

EDIT У меня есть отчетливое чувство, что это никуда меня не приведет. Помимо странного поведения, я также могу заметить, что во время выполнения пользовательского интерфейса в вышеупомянутом случае try catch выполняется точно. Мой пользовательский интерфейс не падает, и он полон пустых строк. Однако, как только я начинаю закрывать пользовательский интерфейс, происходит сбой, и попытка перехвата больше не сдерживает исключение.

РЕДАКТИРОВАТЬ и окончательный По-видимому, файл дампа содержал в нем самое последнее исключение первого шанса. Я проверил это, создав новый проект, который бросил внутрь и поймал 10 секунд. Во время ожидания я получил файл .dmp и, конечно же, обнаружилось мое полностью перехваченное исключение.

Я отмечу несколько баллов за полезные ответы, однако, к сожалению, до сих пор нет ни рифмы, ни причины, по которой мой код падает ...

Ответы [ 5 ]

4 голосов
/ 18 апреля 2010

Добавить исключение в качестве дополнительного улова. Я думаю, что вы получаете какое-то другое исключение, кроме ApplicationException, и именно оно вызывает сбой в вашем приложении.

3 голосов
/ 18 апреля 2010

Существуют различные исключения, которые не могут быть перехвачены. В частности, переполнение стека! Может ли это произойти где-то в вашем коде?

См. http://www.bluebytesoftware.com/blog/PermaLink,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx

0 голосов
/ 18 апреля 2010

Несколько вещей, которые могут помочь с диагнозом:

  • Регистрация для AppDomain.CurrentDomain.UnhandledException, чтобы вы могли видеть, происходит ли сбой в потоке, отличном от потока пользовательского интерфейса

  • Зарегистрируйтесь для Application.ThreadException, чтобы перехватывать любые исключения, не обнаруженные в потоке пользовательского интерфейса

  • Поскольку это происходит во время завершения работы, используете ли вы какие-либо Финализаторы, которые могут быть вызваны потоком финализатора?

0 голосов
/ 18 апреля 2010

Возможно, вы поймали и снова выбросили какое-то другое исключение из Run. Вероятно, _store равен нулю или что-то в этом роде.

0 голосов
/ 18 апреля 2010

Вы пытались добавить предложение "finally"? просто чтобы увидеть, не проигнорирует ли он попытку / поймать полностью? Теоретически он всегда должен переходить к этой строке, прежде чем завершить попытку / отлов, несмотря ни на что.

Если он по-прежнему игнорирует это, то в этом есть что-то определенно странное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...