在我的代码中,以下内容崩溃了在Windows 10 Professional上运行的应用程序.
this.ShowInTaskbar = true;
这已经在2台不同的机器上进行了测试.当我在try/catch块中包含上述代码行时,没有显示异常.我订阅Appdomain.UnhandledException
活动时也没有例外.
Event ID 1000
事件查看器中存在应用程序错误,指出发生了错误,System.Windows.Forms.ni.dll
但没有其他任何我能理解的内容.
此问题也无法在Windows 10 Professional上运行的开发计算机上重现.
除了a之外,表单没有控件NotifyIcon
.经过实验,我发现问题出在以下几行代码上:
private void onFormResize(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) this.ShowInTaskbar = false; } private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) { try { this.ShowInTaskbar = true; this.WindowState = FormWindowState.Normal; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
如果我先更改WindowState
然后在任务栏上显示表单,那么一切都正常.此外,如果我从OnFormResize
应用程序中删除代码也不会崩溃,无论命令执行的顺序如何notifyIcon1_MouseDoubleClick
.
免责声明:大多数是非合同行为,因此不要权威性地使用它 - Windows和.NET Framework的不同版本和配置可能会对正在发生的事情产生微小的影响.
您在任务栏中显示窗口.这需要重新创建窗口,这会导致调整大小.在resize事件处理程序中,您隐藏任务栏中的窗口.这需要重新创建窗口,这会导致调整大小.在resize事件处理程序中,您隐藏了任务栏中的窗口 - 但这不会重新创建窗口,因为"我在任务栏中显示了什么?" 字段实际上已经更新.然而,它进入了臭名昭着的"访问Control.Handle,同时创建一个句柄"无限循环 - 这可能是框架中的一个错误(有趣的是,它发生在窗体最小化或最大化,但不是"正常大小").Control.Handle
打电话Form.RecreateHandleCore
给Control.Handle
你,你做完了:)
为什么不在所有机器上发生这种情况?因为调整大小并不总是必要的.这可能与任何数量的东西有关 - UI主题,字体大小,显示......但基本错误仍然存在 - 您正在导致无限递归.它只是被跳过,因为你少了一个Resize
事件.
为什么你不能抓住这个例外?好吧,StackOverflowException
这种方式可能有点鬼鬼祟祟.您正处于安全关键代码的中间,可能是在本机调用中,并且您获得了堆栈溢出.你究竟如何恢复?所有运行时都知道堆栈防护已被命中 - 据他所知,有人只是替换了程序内存的一半.OutOfMemoryException
非常相似 - 你不知道如何再次进入安全状态,所以唯一的选择是快速失败.
更改WindowState
之前ShowInTaskbar
的问题有两种解决方法 - 一种是改变调整大小处理程序的工作方式 - 这是代码中的错误,更改窗口状态会阻止代码(ShowInTaskbar = false
)运行.第二个是Control.Handle
窗体重新创建其句柄时的访问仅在窗口最小化或最大化时发生 - 这是框架部分.不用说,这很脆弱 - 像这样的错误很难找到并修复.
那么,这样做的正确方法是什么?您希望在最小化时将窗口隐藏在任务栏中.这只是当窗口状态曾经非最小化并且更改为最小化时 - 所以你需要保持旧窗口状态并检查它.
更好,不要乱用ShowInTaskbar
.看起来你正在制造不必要的复杂事物,当你真正想要的是在它被最小化时隐藏它!Show
并且Hide
将会执行,不需要完全信任,也不会在Alt + Tab菜单中保留表单.属性是为了给设计师提供良好的支持 - 但是在创建表单后你不应该真正改变它; 给定的表单显示在任务栏中,或者不显示.没有理由在运行时更改它.ShowInTaskbar
适用于具有多个以某种方式连接的窗口的应用程序 - 例如,在不同表单上显示的模式对话框,具有相同z顺序的多窗口界面等.如果您只需要隐藏表单,请将其隐藏.无需继续创建和销毁所有窗口句柄:)我怀疑框架设计师给我们的唯一原因ShowInTaskbar