2

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.

Exception Thrown

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:

Frozen Application

Does anybody know why this is happening, and how can I avoid it?

Thanks in advance!

Matias Cicero
  • 25,439
  • 13
  • 82
  • 154

4 Answers4

3

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();
    }
}
CL.
  • 173,858
  • 17
  • 217
  • 259
  • Wow, didn't know about that behaviour in `SQLiteTransaction`, thank you very much! It seems you are correct about the uncaught exception, it appears I thought I was catching it from a higher level, but I really wasn't. Thank you all! – Matias Cicero Jul 25 '14 at 19:07
1

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.

bmm6o
  • 6,187
  • 3
  • 28
  • 55
0

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:

  1. The exception is being caught higher up the stack.

  2. 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.

  3. The exception is being thrown on a ThreadPool thread and not being propagated back to the main thread.

Community
  • 1
  • 1
Pat Hensel
  • 1,274
  • 9
  • 11
  • Its come to my attention that #3 is only relevant to .NET version 1.X. But its still possible that the exception is being caught by a try/catch in the wait callback which may not appear in the call stack. – Pat Hensel Jul 25 '14 at 18:02
-1

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;
        }
    }
}
compman2408
  • 2,369
  • 1
  • 15
  • 15
  • 1
    He doesn't want to swallow the exception; that wouldn't make the program function properly. He wants the transaction to be rolled back and then for the exception to continue propogating up. Your assertion that a catch block doesn't catch an exception that it rethrows is false. it does catch it. It rethrows it after doing something (in this case rolling back a transaction) but it does catch it. – Servy Jul 25 '14 at 17:45
  • That's exactly why I am using `throw` @Servy, I could not have explained it better – Matias Cicero Jul 25 '14 at 18:05
  • @MatiCicero Respectfully, I believe it could have been explained a little better. I just edited my answer. Let me know if I'm still not understanding what you want to do. – compman2408 Jul 25 '14 at 18:33