How to Catch All Exceptions/Crashes in a .Net App

How to catch ALL exceptions/crashes in a .NET app

Contrary to what some others have posted, there's nothing wrong catching all exceptions. The important thing is to handle them all appropriately. If you have a stack overflow or out of memory condition, the app should shut down for them. Also, keep in mind that OOM conditions can prevent your exception handler from running correctly. For example, if your exception handler displays a dialog with the exception message, if you're out of memory, there may not be enough left for the dialog display. Best to log it and shut down immediately.

As others mentioned, there are the UnhandledException and ThreadException events that you can handle to collection exceptions that might otherwise get missed. Then simply throw an exception handler around your main loop (assuming a winforms app).

Also, you should be aware that OutOfMemoryExceptions aren't always thrown for out of memory conditions. An OOM condition can trigger all sorts of exceptions, in your code, or in the framework, that don't necessarily have anything to do with the fact that the real underlying condition is out of memory. I've frequently seen InvalidOperationException or ArgumentException when the underlying cause is actually out of memory.

.Net application crashes despite being inside try catch block C#

The reason you're running into this issue is that C# event handlers cannot safely throw exceptions. There is a great StackOverflow answer here which goes into more detail about why, but to paraphrase:

Throwing an exception from an event handler leaves the caller (triggering the event) with very few options about how to safely proceed while guaranteeing that other event handlers also receive the event.

In this case, it sounds like the class triggering the event (Storyboard) does not catch exceptions thrown by event handlers and instead allows the program to crash (which is, in some ways, the safest recourse).

Coming back to your code, you've got something which can broadly be simplified into the following structure:

try
{
var storyboard = new Storyboard();

storyboard.Event += (o, e) => {
throw new Exception("Example");
};

storyboard.Begin();
}
catch (Exception)
{
// Don't crash
}

The problem is that the try-catch block will only catch exceptions thrown by code executing within the call stack of that try-catch. The event handler itself may be executing on the call stack of another thread (in this case, most likely a thread in the ThreadPool) and is not within this try-catch block. This means that unless the Storyboard class catches exceptions from the event handler and then re-throws them within the scope of its Begin() method (which it isn't doing) you will experience an unhandled exception.

To solve this, you simply need to wrap the code inside your event handler in its own try-catch block like this:

storyboard.CurrentTimeInvalidated += (s, e) =>
{
try
{
// TODO: Add your event handler code here
}
catch (Exception ex)
{
// TODO: Handle exceptions triggered within your animation here
}
};

.NET - What's the best way to implement a catch all exceptions handler

I have just played with AppDomain's UnhandledException behavior,
(this is the last stage the unhandled exception is registered at)

Yes, after processing the event handlers your application will be terminated and the nasty "... program stopped working dialog" shown.

:)
You still can avoid that.

Check out:

class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Console.WriteLine("Press enter to exit.");

do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();

} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");

Console.WriteLine("last good-bye");
}

int r = 0;

void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());

Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";

while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}

static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}

P.S. Do handle the unhandled for Application.ThreadException (WinForms) or DispatcherUnhandledException (WPF) at the higher level.

How can I swallow all exceptions and protect my application from crashing?

It would make sense to cure the disease first, find out why it's causing to crash, sure the code is crashing because of obj = null or similar - using exception handling and swallowing all exceptions is just masking the problem....That's what it is not used for! It sounds like there's a lot of code-smells that is triggering the crashes - Protecting your application from crashing is not the right way to deal with it and only making things worse...

Ok, you can follow John Saunders's and pm100's suggestion to do that...but handle it in a manner to see what's the root cause, do not treat it as a 'magic silver bullet', at the end of the day, the code that is interacting with the third party application needs to be debugged thoroughly...

for instance


object foo = null;
bar baz;

// ....
// foo is now set by thirdparty app

if (foo != null && foo is bar) baz = (bar)foo as bar;

if (baz != null){

// Continue on, baz is a legitimate instance of type 'bar'

}else{

// Handle it gracefully or throw a *user defined exception*

}

Notice how the 'as' is used to check if 'foo' is of the right type for 'bar' instance - now compare with this, that is a typical code smell...


object foo = null;
bar baz;

// foo is now set by thirdparty app - ARE YOU REALLY SURE ITS NON-NULL?
// IS IT REALLY OF TYPE 'BAR'?

baz = foo; // CRASH! BANG! WALLOP! KERRUNCH!

Using try/catch for preventing app from crashes

Of course, there are always exceptions to rules, but if you need a rule of thumb - then you are correct; empty catch blocks are "absolutely" bad practice.

Let's have a closer look, first starting with your specific example:

try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) { }

So, a reference to something is created; and when that fails ... it doesn't matter; because that reference isn't used in the first place! The above code is absolutely useless line noise. Or does the person who wrote that code initially assume that a second, similar call would magically no longer throw an exception?!

Maybe this was meant to look like:

try {
View view = findViewById(R.id.toolbar);
... and now do something with that view variable ...
}
catch(Exception e) { }

But again, what does this help?! Exceptions exist to communicate respectively propagate error situations within your code. Ignoring errors is rarely a good idea. Actually, an exception can be treated in ways like:

  • You give feedback to the user; (like: "the value you entered is not a string, try again"); or to engage in more complex error handling
  • Maybe the problem is somehow expected and can be mitigated (for example by giving a "default" answer when some "remote search" failed)
  • ...

Long story short: the minimum thing that you do with an exception is to log/trace it; so that when you come in later debugging some problem you understand "OK, at this point in time that exception happened".

And as others have pointed out: you also avoid catching for Exception in general (well, depending on the layer: there might be good reasons to have some catch for Exception, and even some kinds of Errors at the highest level, to make sure that nothing gets lost; ever).

Finally, let's quote Ward Cunningham:

You know you are working with clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.

Let that sink in and meditate about it. Clean code does not surprise you. The example you are showing to us surprises everybody looking at.

Update, regarding the update that the OP asks about

try {
do something
}
catch(Exception e) {
print stacktrace
}

Same answer: doing that "all over the place" is also bad practice. Because this code is also surprising the reader.

The above:

  • Prints error information somewhere. It is not at all guaranteed that this "somewhere" resembles a reasonable destination. To the contrary. Example: within the application I am working with, such calls would magically appear in our trace buffers. Depending on context, our application might pump tons and tons of data into those buffers sometimes; making those buffer prune every few seconds. So "just printing errors" often translates to: "simply loosing all such error information".
  • Then: you don't do try/catch because you can. You do it because you understand what your code is doing; and you know: I better have a try/catch here to do the right thing (see the first parts of my answer again).

So, using try/catch as "pattern" like you are showing; is as said: still not a good idea. And yes, it prevents crashes; but leads to all kind of "undefined" behavior. You know, when you just catch an exception instead of properly dealing with it; you open a can of worms; because you might run into myriads of follow-on errors that you later don't understand. Because you consumed the "root cause" event earlier on; printed it somewhere; and that somewhere is now gone.



Related Topics



Leave a reply



Submit