在 Try/Catch、Visual Studio 内中断并结束未处理异常的应用程序
Inside Try/Catch, Visual Studio breaks and ends app on Unhandled exception
当 运行 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,则会触发 Wrapper()
内的 Catch ex As Exception
(这是预期结果)。这里有什么问题?
Visual Studio 错误信息是 An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in filename.exe
.
这是在调用 MyForm.Show()
期间发生的,它间接调用 MyForm_Load()
事件处理程序并调用 MyComboBox_SelectedIndexChanged()
事件处理程序(这个间接执行查询) .
如果我在异常中断期间找到并单击 Wrapper()
堆栈帧,我可以看到位于 Try
/[=23 之间的对 FillMyDataTable()
的突出显示调用=].
我总是在主线程上(ManagedThreadId
存储在 Startup
事件期间,然后在上面的代码中插入多个断言验证它)。
堆栈跟踪完全相同(通过 diff 检查)除了最底部的帧(System.Windows.Forms.NativeWindow.DebuggableCallback()
与 System.Windows.Forms.NativeWindow.Callback()
)。
- 最上面的框架是
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
。
直到昨天才出现这个问题。我想我已经改变了一些选项。
重新启动 Visual Studio 没有帮助。
如果启用或禁用异常助手,行为不会发生变化。
选项和异常设置是这样的:
堆栈跟踪是:
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 字节
System.Windows.Forms.dll!System.Windows.Forms.Form.OnCreateControl() + 0x55 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl(bool fIgnoreVisible) + 0x181 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl() + 0x24 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.WmShowWindow(ref System.Windows.Forms.Message m) + 0x98 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x2b6 字节
System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) + 0x2a 字节
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc(ref System.Windows.Forms.Message m) + 0x10 字节
System.Windows.Forms.dll!System.Windows.Forms.Form.WmShowWindow(ref System.Windows.Forms.Message m) + 0x41 字节
System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x154 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 字节
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x57 字节
[本地到管理的过渡]
[管理到原生过渡]
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, 对象 pvParam) + 0x3c 字节
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.CreateHandle(System.Windows.Forms.CreateParams cp) + 0x225 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.CreateHandle() + 0x125 字节
System.Windows.Forms.dll!System.Windows.Forms.Form.CreateHandle() + 0x9f 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() + 0x45 字节
System.Windows.Forms.dll!System.Windows.Forms.Form.SetVisibleCore(布尔值) + 0x160 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.Show() + 0x10 字节
myApp.exe!myApp.APP.clsPrenos.ZobrazWizard(myApp.frmAPP_PrenosWizard.enRezimPrenosu rezim, myApp.APP.clsEntita.enEntita zdrojEntita, 整数 zdrojID, myApp.APP.clsEntita.enEntita cielEntita, 整数 cielID, System.Data.SqlClient.SqlConnection cn1) 第 8212 行 + 0xa字节基础
myApp.exe!myApp.frmMain.FCreateTransferUI(myApp.frmAPP_PrenosWizard.enRezimPrenosu 模式,myApp.APP.clsEntita.enEntita sourceEntity,整数 sourceID,myApp.APP.clsEntita.enEntita targetEntity,整数 targetID,System.Data.SqlClient.SqlConnection cn1) 第 2410 行 + 0x17字节基础
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 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripMenuItem.OnClick(System.EventArgs e) + 0x46 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.HandleClick(System.EventArgs e) + 0x6e 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.FireEventInteractive(System.EventArgs e, System.Windows.Forms.ToolStripItemEventType met) + 0x83 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.FireEvent(System.EventArgs e, System.Windows.Forms.ToolStripItemEventType met) + 0x118 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripMenuItem.ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData) + 0x47 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripManager.ProcessShortcut(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys shortcut) + 0x2dc 字节
System.Windows.Forms.dll!System.Windows.Forms.ToolStripManager.ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData) + 0x2d 字节
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x3c 字节
System.Windows.Forms.dll!System.Windows.Forms.Form.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x29 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x96 字节
System.Windows.Forms.dll!System.Windows.Forms.TextBoxBase.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0xda 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessMessage(ref System.Windows.Forms.Message msg) + 0x90 字节
System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessControlMessageInternal(System.Windows.Forms.Control 目标,参考 System.Windows.Forms.Message 消息) + 0x101 字节
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(ref System.Windows.Forms.NativeMethods.MSG msg) + 0xf6 字节
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage(ref System.Windows.Forms.NativeMethods.MSG msg) + 0x5 字节
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason, int pvLoopData) + 0x22e 字节
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x177 字节
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 字节
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.ApplicationContext 上下文) + 0x18 字节
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() + 0x81 字节
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() + 0xef 字节
Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(string[] commandLine) + 0x68 字节
[本地到管理的过渡]
[管理到原生过渡]
mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.Assembly assembly, string[] args) + 0x19 字节
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e 字节
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x84 字节
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 字节
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xa 字节
mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x3e 字节
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 字节
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(对象状态)+ 0x66 字节
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback 回调, 对象状态) + 0x6f 字节
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 字节
这个问题有很多变化的部分,我不确定我是否能公正地回答所有这些问题。出发点是,如果您使用调试器,则不应订阅这些事件。用 If Not System.Diagnostics.Debugger.IsAttached Then
包装该代码,以便您可以正确诊断和修复未处理的异常。
一个重要的随机化器是 Load 事件处理程序中抛出的异常。 Microsoft 在正确处理 Windows 回调处于活动状态时引发的异常时遇到了很多麻烦。例如导致 Load 事件触发的那个。他们在 Vista 上改变了规则,在 Win7 上又一次在 Win8 上改变了规则。如果您 运行 64 位版本的 32 位版本,它们是不同的。以及您的程序 运行s 是 32 位还是 64 位进程。使用调试器会改变行为。出现异常时可能会出现程序兼容性助手,询问你是否希望你的程序是"compatible"。每个人都说是的,当然,这是一个非常糟糕的主意。将它们相加,您可以获得 三十二 种不同结果中的一种。哎哟
在this MSDN article but nobody understands it. Not until it doesn't do what they hope for, covered in a question like this one中有正式描述。缓解情况是,当您调试应用程序时,这只是字节,消息循环中的正常异常回退确保这不会在您的用户机器上失控。换句话说,当您按下 Ctrl+F5 或 运行 带有资源管理器的程序时,您所看到的就是您期望它的工作方式。
这个问题会影响 Windows 上的 任何 GUI 程序。但它有一个诀窍,在 Winforms 应用程序中特别麻烦,程序员完全使用 Load 事件太多。由于它是表单 class 的默认事件,所以它被迷惑了,只需双击即可生成它。特别是在 VB.NET 中,它不会自动创建窗体的构造函数,并且 Visual Basic 有使用 Load 事件初始化窗体的传统,可以追溯到 VB6。
我通常会避免判断我看到的编程实践,但由于这些问题,今天使用 Load 事件确实是一种相当糟糕的实践。始终支持构造函数初始化一个 class,这是任何 .NET 程序员都知道的规则,对于 Form class 也没有什么不同。 使用 Load 的理由非常少,详见 this post。
当 运行 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,则会触发 Wrapper()
内的 Catch ex As Exception
(这是预期结果)。这里有什么问题?
Visual Studio 错误信息是
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in filename.exe
.这是在调用
MyForm.Show()
期间发生的,它间接调用MyForm_Load()
事件处理程序并调用MyComboBox_SelectedIndexChanged()
事件处理程序(这个间接执行查询) .如果我在异常中断期间找到并单击
Wrapper()
堆栈帧,我可以看到位于Try
/[=23 之间的对FillMyDataTable()
的突出显示调用=].我总是在主线程上(
ManagedThreadId
存储在Startup
事件期间,然后在上面的代码中插入多个断言验证它)。堆栈跟踪完全相同(通过 diff 检查)除了最底部的帧(
System.Windows.Forms.NativeWindow.DebuggableCallback()
与System.Windows.Forms.NativeWindow.Callback()
)。- 最上面的框架是
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
。
- 最上面的框架是
直到昨天才出现这个问题。我想我已经改变了一些选项。
重新启动 Visual Studio 没有帮助。
如果启用或禁用异常助手,行为不会发生变化。
选项和异常设置是这样的:
堆栈跟踪是:
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 字节 System.Windows.Forms.dll!System.Windows.Forms.Form.OnCreateControl() + 0x55 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl(bool fIgnoreVisible) + 0x181 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl() + 0x24 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.WmShowWindow(ref System.Windows.Forms.Message m) + 0x98 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x2b6 字节 System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) + 0x2a 字节 System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc(ref System.Windows.Forms.Message m) + 0x10 字节 System.Windows.Forms.dll!System.Windows.Forms.Form.WmShowWindow(ref System.Windows.Forms.Message m) + 0x41 字节 System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x154 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 字节 System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x57 字节 [本地到管理的过渡] [管理到原生过渡] 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, 对象 pvParam) + 0x3c 字节 System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.CreateHandle(System.Windows.Forms.CreateParams cp) + 0x225 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.CreateHandle() + 0x125 字节 System.Windows.Forms.dll!System.Windows.Forms.Form.CreateHandle() + 0x9f 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() + 0x45 字节 System.Windows.Forms.dll!System.Windows.Forms.Form.SetVisibleCore(布尔值) + 0x160 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.Show() + 0x10 字节 myApp.exe!myApp.APP.clsPrenos.ZobrazWizard(myApp.frmAPP_PrenosWizard.enRezimPrenosu rezim, myApp.APP.clsEntita.enEntita zdrojEntita, 整数 zdrojID, myApp.APP.clsEntita.enEntita cielEntita, 整数 cielID, System.Data.SqlClient.SqlConnection cn1) 第 8212 行 + 0xa字节基础 myApp.exe!myApp.frmMain.FCreateTransferUI(myApp.frmAPP_PrenosWizard.enRezimPrenosu 模式,myApp.APP.clsEntita.enEntita sourceEntity,整数 sourceID,myApp.APP.clsEntita.enEntita targetEntity,整数 targetID,System.Data.SqlClient.SqlConnection cn1) 第 2410 行 + 0x17字节基础 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 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripMenuItem.OnClick(System.EventArgs e) + 0x46 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.HandleClick(System.EventArgs e) + 0x6e 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.FireEventInteractive(System.EventArgs e, System.Windows.Forms.ToolStripItemEventType met) + 0x83 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.FireEvent(System.EventArgs e, System.Windows.Forms.ToolStripItemEventType met) + 0x118 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripMenuItem.ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData) + 0x47 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripManager.ProcessShortcut(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys shortcut) + 0x2dc 字节 System.Windows.Forms.dll!System.Windows.Forms.ToolStripManager.ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData) + 0x2d 字节 System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x3c 字节 System.Windows.Forms.dll!System.Windows.Forms.Form.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x29 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0x96 字节 System.Windows.Forms.dll!System.Windows.Forms.TextBoxBase.ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData) + 0xda 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessMessage(ref System.Windows.Forms.Message msg) + 0x90 字节 System.Windows.Forms.dll!System.Windows.Forms.Control.PreProcessControlMessageInternal(System.Windows.Forms.Control 目标,参考 System.Windows.Forms.Message 消息) + 0x101 字节 System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(ref System.Windows.Forms.NativeMethods.MSG msg) + 0xf6 字节 System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage(ref System.Windows.Forms.NativeMethods.MSG msg) + 0x5 字节 System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason, int pvLoopData) + 0x22e 字节 System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x177 字节 System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 字节 System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.ApplicationContext 上下文) + 0x18 字节 Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() + 0x81 字节 Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() + 0xef 字节 Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(string[] commandLine) + 0x68 字节 [本地到管理的过渡] [管理到原生过渡] mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.Assembly assembly, string[] args) + 0x19 字节 mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e 字节 mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x84 字节 mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 字节 mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xa 字节 mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x3e 字节 Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 字节 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(对象状态)+ 0x66 字节 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback 回调, 对象状态) + 0x6f 字节 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 字节
这个问题有很多变化的部分,我不确定我是否能公正地回答所有这些问题。出发点是,如果您使用调试器,则不应订阅这些事件。用 If Not System.Diagnostics.Debugger.IsAttached Then
包装该代码,以便您可以正确诊断和修复未处理的异常。
一个重要的随机化器是 Load 事件处理程序中抛出的异常。 Microsoft 在正确处理 Windows 回调处于活动状态时引发的异常时遇到了很多麻烦。例如导致 Load 事件触发的那个。他们在 Vista 上改变了规则,在 Win7 上又一次在 Win8 上改变了规则。如果您 运行 64 位版本的 32 位版本,它们是不同的。以及您的程序 运行s 是 32 位还是 64 位进程。使用调试器会改变行为。出现异常时可能会出现程序兼容性助手,询问你是否希望你的程序是"compatible"。每个人都说是的,当然,这是一个非常糟糕的主意。将它们相加,您可以获得 三十二 种不同结果中的一种。哎哟
在this MSDN article but nobody understands it. Not until it doesn't do what they hope for, covered in a question like this one中有正式描述。缓解情况是,当您调试应用程序时,这只是字节,消息循环中的正常异常回退确保这不会在您的用户机器上失控。换句话说,当您按下 Ctrl+F5 或 运行 带有资源管理器的程序时,您所看到的就是您期望它的工作方式。
这个问题会影响 Windows 上的 任何 GUI 程序。但它有一个诀窍,在 Winforms 应用程序中特别麻烦,程序员完全使用 Load 事件太多。由于它是表单 class 的默认事件,所以它被迷惑了,只需双击即可生成它。特别是在 VB.NET 中,它不会自动创建窗体的构造函数,并且 Visual Basic 有使用 Load 事件初始化窗体的传统,可以追溯到 VB6。
我通常会避免判断我看到的编程实践,但由于这些问题,今天使用 Load 事件确实是一种相当糟糕的实践。始终支持构造函数初始化一个 class,这是任何 .NET 程序员都知道的规则,对于 Form class 也没有什么不同。 使用 Load 的理由非常少,详见 this post。