Pergunta

I'm trying to implement valid exception handling in my monodroid app which is written with Xamarin.Android plugin for Visual Studio.

I'm trying to handle 2 types of exceptions:

  1. at foreground (UI) thread
  2. at background (threadpool) thread

In both cases at global handler I'm want to:

  • Logging - (submitting analytics event)
  • User Notification - (alert)

After certain investigation I have found some answers here, here and here but nothing except AndroidEnvironment.UnhandledExceptionRaiser and AppDomain.UnhandledException was proposed and it doesn't work in all cases.

I created short sample where I'm trying to use both handlers:

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;
};

And then on button click I added the following code to raise both types of exceptions:

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

As a result I have different behavior for both types of exceptions:

  1. foreground:
    • both handlers are raised
    • it is impossible to prevent app from being crashed - it will be crashed any way (e.Handled = true is just ignored)
  2. background:
    • only the second handler is raised
    • app doesn't crash

In my case I couldn't wrap every user action in try-catch, especially background tasks. I have business login which should be interrupted in case of error and it is exactly what I expect from runtime. Same time I want to handle those exception on the top level in one place, log them (based on my our business rules) and continue app execution.

How to handle both exception and still have ability to keep app alive (prevent crash).

You can find complete code sample here: https://dl.dropboxusercontent.com/u/19503836/UnhandledException.zip

Thank you for your advice. Any help appreciated. TIA!

Foi útil?

Solução

These event handlers aren't designed to let you recover from the exception, they're a last resort to give you an opportunity to do something like writing to an error log before the application is terminated.

You've mentioned that you want to log errors - that should work fine, but displaying an error to the user might not be possible because your Application will have reached a point where it is not even able to do that.

As the comment on your question mentions, it is a bad idea to handle exceptions like this.

While you might have a very specific expectation of when this is going to be called, your App could throw an exception at any point - and for any reason. It's impossible to design it so that it handles everything correctly.

Even if you could write something to deal with any exception safely, your App will still be terminated because of the unhandled exception.

The Microsoft documentation for AppDomain.CurrentDomain.UnhandledException gives some more information on this:

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

Outras dicas

@Daveoc64 - I disagree with you (and others) that have stressed that global handling of uncaught exceptions is a bad idea - i'd say its a necessity for UI applications. It doesn't negate proper exception handling at the method level (i.e where you can handle and recover from specific exceptions in which context is very important as you stressed) - but it's used in addition to it, as sometimes, when an exception occurs, there is no recovery for the application. Therefore putting a try / catch in code to catch an exception that you cannot recover from is pointless - as whatever you put inside that catch block - you'd have to copy and put inside all other catch blocks for the same sort of unrecoverable errors - i.e display a prompt to the user and gracefully exit.. Why repeat that sort of handling throughout the entire code base over and over again - its rediculous - a global exception handler to cater for that kind of concern makes much more sense!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top