C# - Infinite Loop at Exception Throwing? - c#

I have the following code:
protected void ExecuteInTransaction(Action action)
{
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
try
{
action.Invoke();
transaction.Commit();
}
catch(Exception)
{
transaction.Rollback();
throw;
}
}
}
While testing this class, I managed to throw an exception in order to test the catch branch.
As I'm in Debug mode, I continue the execution of this throwing, to see how the calling class handles it, but the exception is never thrown by the method, instead, it's like the exception is constantly being thrown and caught, thrown and caught all over again, never exiting the function.
In Release mode, the application freezes and stops working:
Does anybody know why this is happening, and how can I avoid it?
Thanks in advance!

There is no infinite loop.
Visual Studio just stops at the place where the uncaught exception would abort the program.
Trying to continue does nothing because there is nothing further to execute (VS just displays the same message again to remind you of that).
If you had a try/catch handler in some calling function, you would be able to debug into there.
(But if that catch handler rethrows again, VS would stop there, too.)
Please note that SQLiteTransaction automatically handles rolling back when an open transaction is disposed; it is designed so that your code can be simpler:
protected void ExecuteInTransaction(Action action)
{
using (var transaction = connection.BeginTransaction())
{
action.Invoke();
transaction.Commit();
}
}

Are you sure there's a catch up the stack that can handle this error? The dialog you showed is what you see when an Exception goes unhandled off the top of your program's Main method. The debugger message actually tells you that it was unhandled, so there is no next statement to step to.

Does anybody know why this is happening, and how can I avoid it?
Its hard to say without seeing your call stack.
In general there are 3 possible options:
The exception is being caught higher up the stack.
There's a kernal mode system call somewhere in your call stack and the exception gets swallowed. This only happens when running a 32 bit application on 64 bit windows. The most notable example being an exception thrown in the OnLoad() method of a Form. See VS2010 does not show unhandled exception message in a WinForms Application on a 64-bit version of Windows for more info.
The exception is being thrown on a ThreadPool thread and not being propagated back to the main thread.

Take the throw; code out of the catch block. If you want to know when the code goes into the catch block then use a breakpoint or Debug.WriteLine().
The catch block of a try/catch doesn't not catch exceptions thrown in itself. So the throw; code is creating an unhandled exception. If you want to test the code that's in the catch block then add the throw; code to the end of the try block.
EDIT:
I didn't realize OP wanted the exception to propogate up the chain. He mentioned nothing about the exception being propagated up the chain and his code shows no support for an exception that propagates up since he doesn't show the code that calls this ExecuteInTransaction(Action) method. A catch block can rethrow the exception that it catches. I agree with that. However the code catch(Exception){ throw; } will not re-enter the same catch block. If it would that would create an infinite loop and that's not what happens. If there is a try/catch block surrounding this then the outer catch block will catch the rethrown exception however his code only includes a single catch block. Therefore when it tries to rethrow the exception there is nothing to catch it and the application breaks.
Try something like this:
private void Main()
{
// Instantiate action variable. I know this wouldn't work, but it's just for show.
Action myAction;
try
{
ExecuteInTransaction(myAction);
}
catch(Exception ex)
{
Debug.WriteLine("Error happened and transaction rolled back. " + ex.Message);
}
}
protected void ExecuteInTransaction(Action action)
{
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
try
{
action.Invoke();
transaction.Commit();
}
catch(Exception ex)
{
transaction.Rollback();
throw ex;
}
}
}

Related

Are these try/catch'es equivalent?

Scenario
I have a method that does database operation (let's say). If during that operation any exception is raised, I just want to throw that exception to the caller. I don't want to do any specific task in the catch block, assuming caller will do whatever it wants to do with that exception. In this scenario, which one is appropriate exception handling technique?
try
{
// Some work that may generate exception
}
catch(Exception)
{
throw;
}
finally
{
// Some final work
}
Is the above equivalent to the following try/catch/finally?
try
{
// Some work that may generate exception
}
catch
{
throw;
}
finally
{
// Some final work
}
Is the above equivalent to the following try/finally?
try
{
// Some work that may generate exception
}
finally
{
// Some final work
}
Which one is better than the other? Which one should be used?
No, they are not equivalent. They may be equivalent in some cases, but the general answer is no.
Different kinds of catch blocks
catch block with a specified exception type
The following will only catch managed exceptions that inherit from System.Exception and then executes the finally block, which will happen regardless of whether an exception was thrown or not.
try
{
// Some work that may generate exception
}
catch (Exception)
{
throw;
}
finally
{
// Some final work
}
catch block without a specified exception type
The following catch block without a type specifier will also catch non-managed exceptions that are not necessarily represented by a managed System.Exception object, and then executes the finally block, which will happen regardless of whether an exception was thrown or not.
try
{
// Some work that may generate exception
}
catch
{
throw;
}
finally
{
// Some final work
}
finally block without a catch block
If you do not have a catch block at all, your finally will still be executed regardless of whether or not an exception occoured.
try
{
// Some work that may generate exception
}
finally
{
// Some final work
}
When are they equivalent?
In case your catch block doesn't specify an exception and only contains the throw; statement, the last two are indeed equivalent. In case you don't care about non-managed exceptions and your catch block only contains the throw; statement, all three can be considered equivalent.
Notes
A note about throw
The following two pieces of code contain a subtle difference. The latter will re-throw the exception, meaning that it will rewrite the exception's stack trace, so these are definitely not equivalent:
catch (Exception e)
{
throw;
}
And
catch (Exception e)
{
throw e;
}
In case you use finally with an IDisposable, the following two pieces of code are almost equivalent, but with some subtle differences:
When the object is null, the using statement won't give you a NullReferenceException
When using the try-finally technique, the variable remains in scope, although it is very discouraged to use any object after it has been disposed. However you can still reassign the variable to something else.
Something obj = null;
try
{
obj = new Something()
// Do something
}
finally
{
obj.Dispose();
}
And
using (var obj = new Something())
{
// Do something
}
You have some good answers so far, but there is an interesting difference that they did not mention so far. Consider:
try { ImpersonateAdmin(); DoWork(); }
finally { RevertImpersonation(); }
vs
try { ImpersonateAdmin(); DoWork(); }
catch { RevertImpersonation(); throw; }
finally { RevertImpersonation(); }
Suppose DoWork throws.
Now the first question at hand is "is there a catch block that can handle this exception", because if the answer is "no" then the behaviour of the program is implementation-defined. The runtime might choose to terminate the process immediately, it might choose to run the finally blocks before it terminates the process, it might choose to start a debugger broken at the point of the unhandled exception, it might choose to do anything it likes. Programs with unhandled exceptions are permitted to do anything.
So the runtime starts looking for a catch block. There's none in this try statement, so it looks up the call stack. Suppose it finds one with an exception filter. It needs to know if the filter will permit the exception to be handled, so the filter runs before impersonation is reverted. If the filter accidentally or deliberately does something that only an admin can do, it will succeed! This might not be what you want.
In the second example, the catch catches the exception immediately, reverts the impersonation, throws, and now the runtime starts looking for a catch block to handle the re-throw. Now if there is a filter it runs after the impersonation is reverted. (And of course the finally then reverts again; I assume that reverting impersonation is idempotent here.)
This is an important difference between these two code snippets. If it is absolutely positively forbidden for any code to see the global state that was messed up by the try and cleaned up by the finally, then you have to catch before finally. "Finally" does not mean "immediately", it means "eventually".
Both of the try / catch statements are equivalent in that they are re-throwing the original exception that was caught. However the empty catch is more broad (as Venemo has already stated, catching unmanaged exceptions). If you are to catch an exception and capture it in a variable you can use it for logging or you can throw a new exception while passing the original exception as an argument - making it the "inner exception".
The finally is going to function the same regardless.
Which one should be used, in a scenario where we don't need logging exception and we explicitly assume caller will handle exception being raised like writing in file stream or sending email.
If the caller will handle the exception and you do not need to log the occurrence of the exception at this level, then you should not be catching at all. If the caller will handle an exception being thrown, there is no need to catch an exception just to re-throw it.
Valid reasons to catch an exception that will be re-thrown:
throw new Exception("WTF Happened", ex); // Use as inner exception
Log exception
Use a finally block to execute some cleanup code

Try catch and re-throw exception

I saw some code the other day in one of our projects that uses a try catch and re-throws the caught exception like this:
try
{
exceptionProneCode();
}
catch(Exception ex)
{
throw ex;
}
Nothing else was done with the exception in the catch block so I'm not even sure why it's re-thrown. I can't see any benefit to actually throwing the same exception again and doing nothing with the exception.
If you re-throw an exception that's caught in the catch block, how does C# handle this? Does it get stuck in an infinite throw/catch loop? Or does it eventually leave the try catch?
Consider these two models:
1- By re-throwing ex:
catch(Exception ex)
{
throw ex;
}
you loose StackTrace. If the exception is logged somewhere the StackTrace containing immediate frames of the call stack (history of method calls) is lost.
2- In contrast by throw:
catch(Exception ex)
{
// do something here
throw;
}
you maintain StackTrace. You can do additional processing and then re-throw the exception without loosing the trace string.
It continues to throw the exception up the calls stack. One thing that this piece of code does that is different from if you didn't catch the exception, it will reset the exception location (call stacks, line #, etc) to where you re-threw the exception, so you won't have the location where the original exception was thrown.
If you're not going to actually do something in the catch block I would recommend not catching, or at the very least rethrowing with just a throw instead of throw ex.
It throws the exception to the caller. But it handles it here so it doesn't throw an unhandled exception. However, honestly, I don't see the benefit of this. Just let it throw the exception. Why? Because an exception is only unhandled if the entire call stack above it doesn't have a try ... catch. This isn't doing anything useful.
Does it get stuck in an infinite throw/catch
loop? Or does it eventually leave the try catch?
No. Yes.
The code provides no benefit and does harm to debugging as noted by everyone else.
A good catch block will catch a specific expected issue and log & continue (the problem doesn't indicate the applications state is corrupt), log and halt (because the application is now in an unknown state and continuing could wreck more harm), do something else (e.g. fall back to an equivalent technology/algorithm), wait and try again.
The default is that something is unexpected, should be logged and the application should be stopped-- either abandoning the page or if a winforms app, revert back to a known state if possible.

C# Scope of exception handling

What is the scope of exception handling in C#. I am currently reviewing some code from another programmer on my team and he has a function laid out somewhat like this:
private void function1() {
try {
function2();
}
catch (Exception ex) {
EmailException(ex.message());
}}
private void function2() {
try {
// Do stuff
}
catch (Exception ex) {
// Handle it here
}}
The bulk of the processing code is in function2. However his reporting handling is in function1. Will an exception in function2 kick back to the function1 handler that sends the report?
Edit:
Thanks for your responses, they all were very helpful!
Assuming // Handle it here does not rethrow the exception, function1 will never see the original exception.
It is possible function2 will raise a new issue in its catch though, much like it's possible EmailException could err in function1.
Only if
a) function2 re-throws the original exception with throw or a new exception with throw new ...
b) an unexpected exception occurs inside function2's catch block or after it (which actually in this case is impossible since the catch block is the last thing that happens in function2).
No, an exception propagates only until it is caught.
However, you can re-throw the exception at the end of the catch in function2, leading to the desired behaviour:
private void function2() {
try {
// Do stuff
}
catch (Exception ex) {
// Handle it here
throw; // <- Re-throw the exception.
// Note this is different from `throw ex;`
}
}
Will an exception in function2 kick back to the function1 handler that sends the report?
No unless
An exception occurs outside of function2's try block
An exception occurs inside the function2 exception block
An exception is thrown e.g. trow or trow ex from function2's exception block
An exception is raised in function2's try block that is automatically retrown like ThreadAbortException
In .net, when an exception occurs, the system will search through the nested try blocks on the stack to determine if there is a catch block that can catch the exception. This occurs before any finally blocks run. If there isn't any block that can catch the exception, the system will invoke an "unhandled exception" handler without running any finally blocks.
If the system that does determine that there is a block that can catch the exception, it will start unwinding the stack and run finally blocks associated with inner try blocks until either it has unwound the stack all the way to the catch block it found, or an exception gets thrown in the execution of a finally block. In the latter situation, the previous exception will be abandoned and not processed further; exception handling will start afresh with the newly-thrown exception.
Although there is a semantic difference between wanting to catch an exception, versus merely wanting to act upon it (but let it be regarded as uncaught), there is no clean way to express that distinction in C#; code which catches an exception is expected to resolve it. The best one can do in C# is use a catch (indicating to the system's exception-processing logic to think one is going to catch the exception) and then use a throw, to indicate one doesn't want to resolve it after all (this will occur after inner "finally" blocks have run). In some other languages such as vb.net, it is possible to act upon exceptions, without catching them, before finally blocks run. While there aren't a huge number of cases where a catch and throw is different from capturing an exception without catching it, there are few cases where the distinction matters. If one is using C# and one wishes to avoid being hostile to surrounding code which might want to capture exceptions from inner code before finalizer blocks run, the best approach is probably to write an exception-handling wrapper method written in vb (or have someone else do it), compile it to a DLL, and then use lambdas to feed such a function methods for it to invoke within a suitable try/filter/catch/finally block.

Continue Program execution even after try catch

When I use try, catch blocks, if any exception is throws the program execution is stopped after the catch is handled. But, I need to continue the program execution even if there is exception. Can any one help me how to do it?
If I understand correctly, here's what you're wanting:
try
{
Statement1(); // <-- Exception is thrown in here
Statement2(); // <-- You want to go here after the catch block executes
}
catch
{
HandleException();
}
Try/catch blocks don't work that way. You would have to rewrite your code as follows, instead:
try
{
Statement1();
}
catch
{
}
try
{
Statement2();
}
catch
{
}
Uncaught exceptions terminate execution.
If an exception is caught and not rethrown, the catch() clause is executed, then the finally() clause (if there is one) and execution then continues with the statement following the try/catch/finally block.
If an exception is caught and rethrown, the catch() clause is executed up to and including the throw statement; the finally() clause (if there is one) is executed), then exception is (re-)thrown and the stack unwinding continues.
As the call stack is unwound, finally() clauses are executed as they go out of scope and Dispose() is called as variables declare in using statements go out of scope.
What does not happen is that control does not (and cannot) resume at the point the original exception was thrown. It sounds like you are catching exceptions at a high level -- such as your Main() method -- and expecting execution to continue at original point of failure.
To make that happen, you need to catch the exception at the point at which handling makes contextual sense, and, having handled the exception, either retry the failing operation or ignore the problem.
Doing exception handling well is rather difficult; hence the dictum that the best exception handling practice is to not handle it. Exceptions are supposed to be just that: exceptional. Your code should not throw exception as a normal matter of course; nor should you generally use exceptions as validation technique or as a flow-of-control operator.
If you handle the exception and do not re-throw it (or another Exception) from your catch block, your program should resume.
Additionally, if you are catching exceptions of a certain type (say IO exceptions), but the code in the try block is throwing a different type (say a SQL exception), your catch block with not catch it and the exception will bubble up till the program terminates.
What exactly are you doing in your catch blocks?
If you talking about function (not program) you can use finally to continue your function
try
{
}
catch(MyException ex)
{
}
finally
{
// other code to be done
}
but if you saying program crashes, the cach without any argument can handle it.
If you've reached out to a method that contains your try and catch, you could just do something like this...
//Start Here
exceptionMethod()
//Code will continue here after you've returned from your catch block in exceptionMethod()
doSomeMoreStuff()
exceptionMethod()
try{
doStuff()
}
catch(Exception e){
return
}
a simple return in your catch block should do the trick.

Why is this SocketException not caught by a generic catch routine?

Our company provides a network component (DLL) for a GUI application.
It uses a Timer that checks for disconnections. If it wants to reconnect, it calls:
internal void timClock_TimerCallback(object state)
{
lock (someLock)
{
// ...
try
{
DoConnect();
}
catch (Exception e)
{
// Log e.Message omitted
// Raise event with e as parameter
ErrorEvent(this, new ErrorEventArgs(e));
DoDisconnect();
}
// ...
}
}
So the problem is, inside of the DoConnect() routine a SocketException is thrown (and not caught). I would assume, that the catch (Exception e) should catch ALL exceptions but somehow the SocketException was not caught and shows up to the GUI application.
protected void DoConnect()
{
//
client = new TcpClient();
client.NoDelay = true;
// In the following call the SocketException is thrown
client.Connect(endPoint.Address.ToString(), endPoint.Port);
// ... (login stuff)
}
The doc confirmed that SocketException extends Exception.
The stacktrace that showed up is:
TcpClient.Connect() -> DoConnect() -> timClock_TimerCallback
So the exception is not thrown outside the try/catch block.
Any ideas why it doesn't work?
If ErrorEvent really raises another exception (per the comment), then DoDisconnect() is never executed.
Otherwise, the exception you see might be coming form DoDisconnect()
I wrote a little program and was unable to reproduce, a SocketException was caught inside a TimerCallback just fine.
So I suggest you re-think your analysis, the problem may not be what you think it is. A few suggestions:
run it outside the Timer. T|hat takes the threading out of the loop.
run it in the debugger. Where does the exception really occur?
step through the exception handling. Is ErrorEvent doing what it should?
Could you post the DoConnect() code?
Also things to try:
Can you catch it in the DoConnect()?
Try catching the specific exception instead of just the generic.
How does it react if you use debug mode?
Your timClock_TimerCallback isn't called in the same thread as the catch-statement wants to catch an exception. You should catch the exception inside timClock_TimerCallback and then call a method which invokes itself and then rethrow the exception in the right thread.
Not sure this will work, but you could give it a try.

Categories