I'm trying to use the best possible practices for exception handling and I'm a little bit lost.
For example, if I have 4 methods (1 call the other one who call the other one...).
For each method, a custom exception of the same type can be thrown.
Let's say that I have an error that is thrown in 4th method. Do I need to catch it in the 3rd one or I can catch it in the first one?
Because if I respect the principle that an error needs to be caught as soon as possible, I should put catch in all of the 3 first method instead of only the first one.
Method1()
{
Method2();
}
Method2()
{
Method3();
}
Method3()
{
Method4();
}
Method4()
{
//Some code that could throw a customException
}
I'm trying to use the best possible practices for exception handling and I'm a little bit lost.
Writing robust software is hard.
if I respect the principle that an error needs to be caught as soon as possible
That's a poor principle. What does possibility have to do with it? The principle that you should only write possible code is not helpful. What does time have to do with it? It's a tautology that the correct place to handle an exception is where the exception can be correctly handled; neither sooner nor later than that.
Where can an exception be correctly handled? That depends entirely on (1) the exception and (2) how you intend to handle it. That sounds like very unhelpful advice, but your question is incredibly vague! Let's leave exceptions out of it and just consider computations. Where is the best place to put a computation? Is it better to do computations earlier or later? How could you possibly answer that question for all possible computations?
I just want to avoid to catch same type of error in all my methods so I could just put a catch in my big method?
Well let's think about this. Suppose for the sake of argument that it is correct for each method to handle the exception. Under what circumstances is it correct to move the exception handling out of each callee and into the caller? That's easy to enumerate:
The handlers must not depend on any state known only to the callees but not to the caller.
The handlers have to do the same thing in each callee.
The callees must not be called from anywhere other than the caller.
Is that the situation you're in? Then it is possible to move the handler into the caller without changing semantics, and thereby reducing duplicated code.
I want to close my application, so log the error and close my app
Then put the handler as close to Main as possible.
Alternatively, handle the "I'm unloading the appdomain because I got an unhandled exception" event and put your handling logic there.
I note that if your app is shutting down abnormally like this you have no guarantee that your logging system isn't the thing that blew up, and you might be about to blow it up again. Be careful!
Related
I have been asked to add error logging to an application that logs whenever an exception is thrown.
I have a method which will perform the log and I could call this in every Catch clause.
This seems daft as there are literally hundreds of try catch statements in the app.
In visual studio you can set the IDE to break after every exception regardless of try catches, so I am wondering if this sort of functionality is possible to use (albeit not breakpointing the code when thrown)
in summary my question is:
Is there a way to fire an event (or similar) that would call this method, whenever a custom or CLR exception is thrown.
as a bonus question related to this, is it possible to do similar with method entry / exit logging?
C#
.Net 4.5
VS 2012
If you want your function to be called just like how Visual Studio would break on a first chance exception (breaks on a throw even inside a try-catch block) then you need to subscribe to the FirstChanceExecption event in the AppDomain you are running in.
AppDomain.CurrentDomain.FirstChanceException += YourLoggingFunction;
You need to do this for every AppDomain in your program, but unless you are doing non-common tasks 99% of all programs will likely only ever have a single AppDomain
See this MSDN page for more information about subscribing to other AppDomains if you are using them.
Be aware, you may get more exceptions than you realize, some .NET framework code throws exceptions internally and just have the code in try-catch blocks so it never comes up to the surface1 or if the library code has the pattern
try
{
SomeFunctionThatThrows()
}
catch (Exception innerException)
{
throw new SomeMoreDetailedException(message, stateDetails, innerException);
}
subscribing to the event will cause you to start seeing both the exception thrown from SomeFunctionThatThrows() and from throw new SomeMoreDetailedException(2.
1: This is most common in network based I/O calls where an exception like a TimeoutException would be common but the end user does need to know a timeout error happened as there may be things like internal retry logic that happens before the user is notified.
2: You could also see them in Visual Studio by disabling "Just My Code" and breaking on all thrown exceptions.
I'm in the needing of write a custom exception handler...
MY application is probably going to throw different kind of exceptions, and I would like they all get handled by a single handler (so that I don't need to use thousands of "try-catch" blocks).
I tried with the AppDomain's UnhandledException handler, but it seems that, when an exception is caught, the application will inevitably be closed.
So, is there any way I could accomplish my idea?
EDIT:
Thank you for your rapid replies, but I'd like to make you understand better my situation: I have, for example, a class which throws a custom exception (reversible). Now, this class, is called by multiple other class, so I would need to write a try-catch block on every single one of them (or at least this is what your replies make me think about)..
So, here comes the needing of have an handler capable of catch them all...
You should catch specific exceptions at the point in your code where you are best able to handle them. This should not result in thousands of try-catch blocks, rather, you should find localised areas of exception handling.
I tend to handle exceptions at service boundaries, for example, when interacting with databases or file-systems. At these service boundaries you can handle an exception and perform some logical recovery.
If you find yourself writing try-catch blocks where the catch does not add value, does not help your code recover, then you are not adding value by catching the exception!
You shouldn't need 'thousands' of try/catch blocks.
Only catch what you understand at the points where you can make a decision.
Catching an exception is very much part of your logic (unlike try/finally) and using 1 central handler usually won't do.
Consider this as an opportunity to study the proper use of exceptions.
You can use the AppDomain's UnhandledException Handler without closing the application. I do it too to log missed exceptions:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Program_UnhandledException);
And
private static void Program_UnhandledException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
//Handle the exception here...
}
Yet I do agree with the other answers, usually you shouldn't need a catch all exception handler. Handling exceptions where they occur should be the preferred action.
Edit: I don't know if it works the same way in console applications too.
Wrap your code in a try and catch block, which catches a Exception. All Exceptions are derived from Exception, so every exception that is thrown and not handled elsewhere is caught here. But remember if an exception is thrown, you deal with a possible invalid state of your application. You can't just always continue after an exception.
Another, rather direct approach is to register to the Application.ThreadException(WinForms) but again, you should not use this if you plan to continue running the application. This is for cases where you want to display a message, maybe a way to send the error report and then close the application.
try
{
// Code that needs exception handling
}
catch (Exception ex)
{
// Handle exception. You may use ex.GetType()
}
If this is not adequate, please explain why in your question.
Is it possible to catch an exception from anywhere in a console app that would cause the app to terminate? I'm trying to do this without having and try{} catch{} around everything.
You can use AppDomain.CurrentDomain.UnhandledException event which will catch all unhandled exceptions.
Also check this thread for reference: .NET Global exception handler in console application
Try - catch in your main will not be able to catch exceptions from other threads, for example.
Exceptions "bubble up" to the calling method so having a try-catch block in your Main method is enough to catch everything.
The next important question is what you are going to do with exceptions at top level. Once you are back at that level it is often impossible to make any relevant error recovery except retrying the operation. It is often much better to catch any exceptions that are likely to occur at the site where they are thrown and implement recovery code there.
Go to Debug->Exceptions (Ctrl+D,E) and check appropriate Exception you want to handle. There's an option to break on all 'Thrown' and 'User-unhandled' exception.
You probably want to select 'Common Language Runtime Exception' that are 'Thrown' and 'User-unhandled'. This would break execution any time a CLR exception occurs.
See Most Useful VS Feature No One Knows About
AppDomain.CurrentDomain.UnhandledException += OnCurrentDomain_UnhandledException;
//in windows forms you need also to add these two lines
Application.ThreadException += OnApplication_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
In a console app you can simply wrap the Main loop in a Try Catch Block. You should know that there are a handful of exceptions that will cause the application to terminate without hitting this block.
Also power failure and setting Environment.FailFast to true will ignore this block.
StackoverflowException msdn docs (You can actually catch it you just shouldn't knowledge here)
Environment.FailFast msdn docs
Check out the AppDomain.CurrentDomain.UnhandledException API for creating an app-global exception handler. And here's a nice blog post about implementing/using it with C# and VB.
Also reconsider your approach to exception handling. Structured exception handling should save you the trouble of needing to deal with 'errors all over the place' because the exceptions percolate up the call stack automatically. This means that if you take advantage of exception handling properly then you will have a small number of points in your code where you handle particular exceptions. You definitely should not try and catch everywhere, all the the time.
A try{} / catch{Exception} in your top-level will catch anything thrown from below before it becomes an "uncaught exception".
We have an interface IPoller for which we have various implementations. We have a process that will take an IPoller and start it in a separate thread. I'm trying to come up with a generic way of providing exception handling for any IPollers which don't do it themselves.
My original thinking was to create an implementation of IPoller that would accept an IPoller and just provide some logging functionality. The question I ran into though is how would I provide this error handling? If I have IPoller.Start() which is the target for the Thread is that where the exception will occur? Or is there something on the thread itself I can hook into?
Something like:
Thread thread = new Thread(delegate() {
try
{
MyIPoller.Start();
}
catch(ThreadAbortException)
{
}
catch(Exception ex)
{
//handle
}
finally
{
}
});
This will ensure the exception doesn't make it to the top of the thread.
You should catch the exception at the method you use at the top of the thread, and do the logging from there.
An unhandled exception (at the top of a thread) will (in 2.0 onwards) kill your process. Not good.
i.e. whatever method you pass to Thread.Start (etc) should have a try/catch, and do something useful in the catch (logging, perhaps graceful shutdown, etc).
To achieve this, you could use:
static logging methods
captured variables into the delegate (as an anonymous method)
expose your method on an instance that already knows about the logger
In .NET 4.0+ you should use Tasks instead of threads. Here's a nice article on exception handling in Task Parallel Library
Take a look at AppDomain.UnhandledException, it will help you at least log those exceptions that you are not handling, and in some cases close down "nicely":
This event provides notification of
uncaught exceptions. It allows the
application to log information about
the exception before the system
default handler reports the exception
to the user and terminates the
application. If sufficient information
about the state of the application is
available, other actions may be
undertaken — such as saving program
data for later recovery. Caution is
advised, because program data can
become corrupted when exceptions are
not handled.
Have a look at
Appdomain.FirstChanceException event
It tells you moment any exception occurs and CLR is looking for stack trace. Also event args tell which type of exception. You can consider it as the central place for logging.
I got TargetInvocationException while doing long process in another thread caused by a windows control on UI thread (Progress Bar). This exception leads my app to crash (goes to main method in debugging) and could not be caught by try catch.
I figured out what made this exception, and fix it (that was trying to assign “Value” property by a value that exceeds the maximum). But it made me wondering how I can catch exception like this (in production code) so I have an option to recover my application instead of terminating the application.
Chances are you aren't going to be able to recover very much. In terms of your operation, the state of a good number of stack frames (and objects referenced from those stack frames) is probably invalid because of the error.
Because of that, at best you can recover at a very high level and try the operation again.
If the resources you are accessing are able to be contained in a transaction, then I would suggest doing that, so that you don't have to worry about inconsistencies in persisted data.
Also, you might want to check out this thread on SO:
Best Practice for Exception Handling in a Windows Forms Application?
As well as the Exception Handling Application block from Microsoft:
http://msdn.microsoft.com/en-us/library/cc309505.aspx
You can 'handle' exceptions (really, you're just receiving notification of them) on the GUI thread via the static event Application.UnhandledException.
When you attach a handler to this event, it will be invoked for all unhandled exceptions on the WinForms UI (message pump) thread. The fact that you have this handler attached means that the Application won't exit. Without it, WinForms shuts down your application.
Catch the exception and find a mechanism to pass it back to the main or calling code.
Not sure what version of .net you are using if its 3.0+ you can do something along these lines.
private void UpdateValue(int newValue)
{
Action myAction = () => progressBar.Value = newValue;
if (progressBar.InvokeRequired)
progressBar.Invoke(myAction);
else
myAction();
}
Call this method with the new value for the progress bar it will check if the call needs marshalling and make the appropriate call. Be careful InvokeRequired is relatively expensive, so use it only where needed. You could make this into an extension method to make generic use of this pattern for other controls if needed.
Hope this helps.