Как обрабатывать исключения MonoDroid во всех случаях и предотвращать крах приложения

Я пытаюсь реализовать правильную обработку исключений в моем приложении для монодироидов, которое написано с помощью плагина Xamarin.Android для Visual Studio.

Я пытаюсь обрабатывать 2 типа исключений:

  1. На переднем плане (UI)
  2. В фоновом режиме (threadpool)

В обоих случаях в глобальном обработчике я хочу:

  • Ведение журнала – (отправка события аналитики)
  • Уведомление пользователя – (предупреждение)

После определенного расследования я нашел несколько ответов здесь , здесь и здесь, но ничего, кроме AndroidEnvironment.UnhandledExceptionRaiser и AppDomain.UnhandledException, было предложено, и оно не работает во всех случаях.

Я создал короткий образец, где я пытаюсь использовать оба обработчика:

AppDomain.CurrentDomain.UnhandledException += (s,e)=> { System.Diagnostics.Debug.WriteLine("AppDomain.CurrentDomain.UnhandledException: {0}. IsTerminating: {1}", e.ExceptionObject, e.IsTerminating); }; AndroidEnvironment.UnhandledExceptionRaiser += (s, e) => { System.Diagnostics.Debug.WriteLine("AndroidEnvironment.UnhandledExceptionRaiser: {0}. IsTerminating: {1}", e.Exception, e.Handled); e.Handled = true; }; 

И затем при нажатии кнопки я добавил следующий код для повышения обоих типов исключений:

 //foreground exception throw new NullReferenceException("test nre from ui thread."); //background exception ThreadPool.QueueUserWorkItem(unused => { throw new NullReferenceException("test nre from back thread."); }); 

В результате у меня другое поведение для обоих типов исключений:

  1. на переднем плане:
    • Оба обработчика подняты
    • Невозможно предотвратить повреждение приложения – он будет разбит любым способом (e.Handled = true просто игнорируется)
  2. задний план:
    • Поднят только второй обработчик
    • Приложение не падает

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

Как справиться с обоими исключениями и по-прежнему иметь возможность поддерживать приложение в активном состоянии (предотвращение сбоя).

Вы можете найти полный пример кода здесь: https://dl.dropboxusercontent.com/u/19503836/UnhandledException.zip

Спасибо за ваш совет. Любая помощь оценивается. ТИА!

Solutions Collecting From Web of "Как обрабатывать исключения MonoDroid во всех случаях и предотвращать крах приложения"

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

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

Как говорится в комментарии к вашему вопросу, это плохая идея справиться с такими исключениями.

Хотя у вас может быть очень определенное ожидание того, когда это будет вызвано, ваше приложение может выбросить исключение в любой момент – и по любой причине. Невозможно спроектировать его так, чтобы он правильно справлялся.

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

Документация Microsoft для AppDomain.CurrentDomain.UnhandledException содержит дополнительную информацию об этом:

http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

@ Daveoc64 – Я не согласен с вами (и другими), которые подчеркнули, что глобальная обработка исключений, которые не были обнаружены, – плохая идея – я бы сказал, что это необходимо для приложений пользовательского интерфейса. Это не отменяет правильную обработку исключений на уровне метода (т. Е. Где вы можете обрабатывать и восстанавливать определенные исключения, в которых контекст очень важен, как вы подчеркивали), – но он используется в дополнение к нему, поскольку иногда, когда возникает исключение, Нет восстановления для приложения. Поэтому включение try / catch в код, чтобы поймать исключение, из которого вы не можете восстановить, бессмысленно – как и все, что вы помещаете внутри этого блока catch, вам придется копировать и помещать внутри всех других блоков catch для тех же самых невосстановимых ошибок – Т.е. отображать запрос пользователю и изящно выходить из него. Зачем снова и снова повторять этот вид обработки по всей кодовой базе – его смешной – глобальный обработчик исключений для удовлетворения такого рода озабоченности имеет гораздо больший смысл!