我有以下代码:
protected void ExecuteInTransaction(Action action)
{
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
try
{
action.Invoke();
transaction.Commit();
}
catch(Exception)
{
transaction.Rollback();
throw;
}
}
}
在测试此类时,我设法抛出异常以测试catch
分支。
当我在调试模式下,我继续执行此抛出,以查看调用类如何处理它,但异常是永远不会被方法抛出,相反,它就像不断被抛出并被捕获,抛出并重新捕获,永远不会退出函数。
在发布模式下,应用程序冻结并停止工作:
有谁知道为什么会这样,我怎么能避免呢?
提前致谢!
答案 0 :(得分:3)
没有无限循环。 Visual Studio只停留在未捕获的异常将中止程序的位置。 尝试继续没有任何作用,因为没有进一步执行(VS只是再次显示相同的消息以提醒您)。
如果你在某个调用函数中有一个try / catch处理程序,你就可以调试到那里。 (但是如果那个捕获处理程序再次重新抛出,VS也会停在那里。)
请注意SQLiteTransaction
会在处理未结交易时自动处理回滚;它的设计使您的代码更简单:
protected void ExecuteInTransaction(Action action)
{
using (var transaction = connection.BeginTransaction())
{
action.Invoke();
transaction.Commit();
}
}
答案 1 :(得分:1)
你确定在堆栈中catch
可以处理这个错误吗?您显示的对话框是您在程序的Main
方法顶部未处理异常时看到的内容。调试器消息实际上告诉您它未被处理,因此没有下一个语句可以步骤。
答案 2 :(得分:0)
有谁知道为什么会这样,我怎么能避免呢?
很难说没有看到你的电话堆栈。
一般来说,有3种可能的选择:
异常被捕获到了堆栈中。
你的调用堆栈中某处有一个内核模式系统调用,并且异常被吞下。这仅在64位窗口上运行32位应用程序时发生。最值得注意的示例是OnLoad()
的{{1}}方法中抛出的异常。有关详细信息,请参阅VS2010 does not show unhandled exception message in a WinForms Application on a 64-bit version of Windows。
在Form
线程上抛出异常,而不是传播回主线程。
答案 3 :(得分:-1)
从catch块中取出throw;
代码。如果您想知道代码何时进入catch块,请使用断点或Debug.WriteLine()
。
try / catch的catch块不会捕获自身抛出的异常。所以throw;
代码正在创建一个未处理的异常。如果要测试catch块中的代码,请将throw;
代码添加到try块的末尾。
修改强>
我没有意识到OP希望例外传播链。他没有提到在链上传播的异常,他的代码显示不支持传播的异常,因为他没有显示调用此ExecuteInTransaction(Action)
方法的代码。 catch块可以重新抛出它捕获的异常。我同意这一点。但是代码catch(Exception){ throw; }
不会重新进入相同的catch块。如果它会创建一个无限循环,那不会发生什么。如果有一个try / catch块,那么外部catch块将捕获重新抛出的异常,但是他的代码只包含一个catch块。因此,当它试图重新抛出异常时,没有什么可以捕获它并且应用程序中断了。
尝试这样的事情:
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;
}
}
}