在Try / Catch内部,Visual Studio在Unhandled异常中断开并结束应用程序

时间:2015-02-28 11:58:24

标签: .net visual-studio visual-studio-2012 exception-handling try-catch

我在Visual Studio内外运行相同的代码时会遇到不同的行为。

Private Sub MyApplication_Startup(...) Handles Me.Startup
    '--- handler for unhandled exceptions
    AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledExHandler
    '--- handler 0
    AddHandler System.Windows.Forms.Application.ThreadException, AddressOf ThreadExHandler
    Utils.RememberMainThreadId()
End Sub

Sub OpenMyForm()  'entry point
    Debug.Assert(Utils.RunningOnMainThread())
    Try
        MyForm.Show()  
    Catch ex As Exception  '--- handler 1
        LogError(ex)   '--- goes here only if launched outside the Visual Studio
    End Try
End Sub

Sub MyForm_Load() Handles MyBase.Load
    Debug.Assert(Utils.RunningOnMainThread())
    FillMyDataTable() '---if I put try/catch here, it will always work (tested)
End Sub

Sub FillMyDataTable()
    Try
        New SqlClient.SqlDataAdapter(sqlCmd).Fill(myDataTable)
    Catch ex As Exception '--- handler 2
        If ex.Number = Constants.ConnectionBroken then
            ReconnectRetry()
        Else
            Throw  '--- enters UnhandledExHandler() when in Visual Studio
        End If
    End Try
End Sub

在Visual Studio中,错误的SQL命令出错 UnhandledExHandler(), 但是如果在VS外部启动相同的EXE,则会触发Catch ex As Exception内的Wrapper()(这是预期的结果)。这有什么不对?

  • Visual Studio错误消息为An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in filename.exe

  • 这是在调用MyForm.Show()期间发生的,它间接调用MyForm_Load()事件处理程序并调用MyComboBox_SelectedIndexChanged()事件处理程序(这个间接执行查询)。

  • 如果我在中断期间找到并点击Wrapper()堆叠框架,我可以看到位于FillMyDataTable() / Try之间的Catch被忽略的电话。< / p>

  • 我总是在主线程上(ManagedThreadId存储Startup事件,然后多个断言验证它是否插入上面的代码中。

  • 堆栈跟踪完全相同(通过差异检查),除了最底部的框架(System.Windows.Forms.NativeWindow.DebuggableCallback()System.Windows.Forms.NativeWindow.Callback())。

    • 最上面的框架是System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
  • 直到昨天才出现问题。我想我已经改变了一些选择。

  • 重启Visual Studio没有帮助。

  • 如果启用或禁用了异常助手,则行为没有变化。

  • 选项和例外设置如下:
    enter image description here
    enter image description here

  • 堆栈跟踪是:

myApp.exe!myApp.frmAPP_PrenosWizard.frmFT_PrenosWizard_Load(Object sender, System.EventArgs e) Line 125 Basic
System.Windows.Forms.dll!System.Windows.Forms.Form.OnLoad(System.EventArgs e) + 0x1d5 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Form.OnCreateControl() + 0x55 bytes   
System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl(bool fIgnoreVisible) + 0x181 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl() + 0x24 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.WmShowWindow(ref System.Windows.Forms.Message m) + 0x98 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x2b6 bytes 
System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) + 0x2a bytes    
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc(ref System.Windows.Forms.Message m) + 0x10 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Form.WmShowWindow(ref System.Windows.Forms.Message m) + 0x41 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x154 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x57 bytes 
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.UnsafeNativeMethods.CreateWindowEx(int dwExStyle, string lpszClassName, string lpszWindowName, int style, int x, int y, int width, int height, System.Runtime.InteropServices.HandleRef hWndParent, System.Runtime.InteropServices.HandleRef hMenu, System.Runtime.InteropServices.HandleRef hInst, object pvParam) + 0x3c bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.CreateHandle(System.Windows.Forms.CreateParams cp) + 0x225 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.CreateHandle() + 0x125 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Form.CreateHandle() + 0x9f bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() + 0x45 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Form.SetVisibleCore(bool value) + 0x160 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.Show() + 0x10 bytes   
myApp.exe!myApp.APP.clsPrenos.ZobrazWizard(myApp.frmAPP_PrenosWizard.enRezimPrenosu rezim, myApp.APP.clsEntita.enEntita zdrojEntita, Integer zdrojID, myApp.APP.clsEntita.enEntita cielEntita, Integer cielID, System.Data.SqlClient.SqlConnection cn1) Line 8212 + 0xa bytes   Basic
myApp.exe!myApp.frmMain.FCreateTransferUI(myApp.frmAPP_PrenosWizard.enRezimPrenosu mode, myApp.APP.clsEntita.enEntita sourceEntity, Integer sourceID, myApp.APP.clsEntita.enEntita targetEntity, Integer targetID, System.Data.SqlClient.SqlConnection cn1) Line 2410 + 0x17 bytes  Basic
myApp.exe!myApp.frmMain.frmMain_Receive(Object sender, myApp.clsFisCommandProcessor.ReceivedEventArgs e) Line 239 + 0xa7 bytes  Basic
myApp.exe!myApp.clsFisCommandProcessor.raise_Received(Object sender, myApp.clsFisCommandProcessor.ReceivedEventArgs e) Line 96 + 0x2e bytes Basic
myApp.exe!myApp.clsFisCommandProcessor.Execute(myApp.clsFisCommand command, Object sender) Line 136 + 0x57 bytes    Basic
myApp.exe!myApp.clsFisCommandProcessor.Execute(myApp.clsFisCommand() commands, Object sender) Line 128 + 0x27 bytes Basic
myApp.exe!myApp.clsFisCommandProcessor.Execute(String scan, Boolean requireMarking, Object sender) Line 122 + 0x30 bytes    Basic
myApp.exe!myApp.frmCommandPad.TSMI_Execute_Click(Object sender, System.EventArgs e) Line 94 + 0x51 bytes    Basic
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.RaiseEvent(object key, System.EventArgs e) + 0x58 bytes 
System.Windows.Forms.dll!System.Windows.Forms.ToolStripMenuItem.OnClick(System.EventArgs e) + 0x46 bytes    
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.HandleClick(System.EventArgs e) + 0x6e bytes    
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.FireEventInteractive(System.EventArgs e, System.Windows.Forms.ToolStripItemEventType met) + 0x83 bytes  
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.FireEvent(System.EventArgs e, System.Windows.Forms.ToolStripItemEventType met) + 0x118 bytes    
System.Windows.Forms.dll!System.Windows.Forms.ToolStripMenuItem.ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData) + 0x47 bytes   
System.Windows.Forms.dll!System.Windows.Forms.ToolStripManager.ProcessShortcut(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys shortcut) + 0x2dc bytes    
System.Windows.Forms.dll!System.Windows.Forms.ToolStripManager.ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData) + 0x2d bytes    
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x3c bytes  
System.Windows.Forms.dll!System.Windows.Forms.Form.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x29 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x96 bytes   
System.Windows.Forms.dll!System.Windows.Forms.TextBoxBase.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0xda bytes   
System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessMessage(ref System.Windows.Forms.Message msg) + 0x90 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessControlMessageInternal(System.Windows.Forms.Control target, ref System.Windows.Forms.Message msg) + 0x101 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(ref System.Windows.Forms.NativeMethods.MSG msg) + 0xf6 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage(ref System.Windows.Forms.NativeMethods.MSG msg) + 0x5 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason, int pvLoopData) + 0x22e bytes  
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x177 bytes  
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.ApplicationContext context) + 0x18 bytes 
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() + 0x81 bytes    
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() + 0xef bytes   
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(string[] commandLine) + 0x68 bytes  
[Native to Managed Transition]  
[Managed to Native Transition]  
mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.Assembly assembly, string[] args) + 0x19 bytes 
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e bytes 
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x84 bytes 
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 bytes 
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xa bytes 
mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x3e bytes   
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 bytes   
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   

1 个答案:

答案 0 :(得分:3)

这个问题有许多可动的部分,不确定我能否对所有这些部分公正。起点是,如果使用调试器,则不应订阅这些事件。用If Not System.Diagnostics.Debugger.IsAttached Then包裹该代码,以便您可以正确诊断和修复未处理的异常。

重要的随机化器是在Load事件处理程序中抛出的异常会发生的事情。 Microsoft在正确处理Windows回调处于活动状态时引发的异常时遇到了很多麻烦。例如导致Load事件触发的那个。他们再次在Win8上再次在Win7上更改了Vista的规则。如果运行64位版本的32位,它们会有所不同。以及您的程序是以32位还是64位进程运行。使用调试器会改变行为。异常发生时可能会出现程序兼容性助手,询问您是否希望程序“兼容”。每个人都说是的,这是一个非常糟糕的主意。添加它们,您可以获得 32个不同结果之一。哎哟。

它在this MSDN article中正式描述,但没有人理解它。直到它没有做他们希望的事情,在问题like this one中提到。缓解情况是,在调试应用程序时,这只是字节,消息循环中的正常异常后退可确保在用户的计算机上不会失控。换句话说,当您按下Ctrl + F5或使用资源管理器运行程序时所看到的内容就是您希望它工作的方式。

这是影响Windows上任何 GUI程序的问题。但它在Winforms应用程序中具有特别麻烦的诀窍,程序员完全使用Load事件。由于它是Form类的默认事件而被删除,只需双击即可生成它。特别是在VB.NET中,它不会自动为表单创建构造函数,Visual Basic有使用Load事件初始化表单的遗留问题,返回VB6。

我通常会避免判断我看到的编程实践,但是由于这些问题,今天使用Load事件是一种非常糟糕的做法。总是喜欢构造函数初始化一个类,这是任何.NET程序员都知道的规则,对于Form类来说它没有什么不同。 拥有使用Load的原因极少,this post中涵盖了。