我一直对Ivan Krivyakov很好地引用过的可怕的OnUserPreferenceChanged Hang感到困扰,在这里:

http://ikriv.com/en/prog/info/dotnet/MysteriousHang.html#BeginInvokeDance

当我最初遇到问题时,我不久前发布了一个问题:

Yet another C# Deadlock Debugging Question

我以为我已经通过删除从UI线程构建的控件解决了它,但是过了一会儿它又重新出现了(可能再也没有出现过……)。

我们一直在使用.NET 3.5,据我所知使用的是CLR 2.0。最近,该应用程序已升级为使用.NET 4.0客户端配置文件/CLR 4.0。此外,我们已经从Infragistics WinForms 10.1升级到了10.3。唯一的不同是以前的版本被混淆了...有人在混淆和挂起时遇到过问题吗?

我一劳永逸地摆脱了所有应用程序挂起的问题,但是,不寻常的是,我无法在最新版本(使用.NET 4.0)中重现该挂起。使用Ivan Krivyakov的方便的Freezer应用程序(请参阅他的文章),可以很容易地在以前的版本(使用.NET 3.5)中重现该挂起,该应用程序根据请求触发WM_SETTINGCHANGE消息。

我可能有点希望该问题自行消失,但是没有人知道CLR是否从2.0更改为4.0会导致这种情况吗?

------------------------------------------------- - - 解决方案 - - - - - - - - - - - - - - - - - - - - - - - -----

因此,在测试应用程序的变化之后,例如CLR 2.0 + Infragistics 2010.1,CLR 2.0 + Infragistics 2010.3和CLR 4.0 + Infragistics 2010.1,我们认为我们已经确定问题是WinForms 2010.1中Infragistics组件的问题(无修补程序)。我们仍然没有使用CLR 2.0或带有Infragistics 2010.3的CLR 4.0来重现冻结(并且我们现在非常擅长重现此冻结...)。

最佳答案



是的,这是触发此问题的好方法。根本的问题是由SystemEvents类引起的,它具有令人羡慕的任务,即在正确的线程上引发其事件。 UserPreferenceChanged事件是典型的麻烦制造者,许多控件都订阅了该事件,因此当用户更改桌面主题时,它们可以重新绘制自身。组件供应商不会忽略此需求。工具箱中也没有标准的.NET框架控件。

测试此问题的一种通常不错的方法是锁定工作站(按Win + L键),这也是通常在用户计算机上触发死锁的方式。切换到安全桌面倾向于触发事件。伴随着其他怪癖,当您调试程序时,这永远不会发生,并且它具有棘手的与时间相关的行为,因为当没有人在机器上时,这往往会发生。特别难以调试。

遇到这种麻烦的一种标准方法是由于程序中的初始化问题。预订的第一个SystemEvents事件导致SystemEvents类初始化自身并设置接收这些通知并引发其相应事件所需的管道。一个自定义启动屏幕执行了太多操作(即,不仅仅是显示位图),并且在标记为STA的工作线程上运行足以解决此问题。像ProgressBar这样简单的东西就足够了。 SystemEvents假定工作线程是程序的主线程,现在可以在将来轻松地在错误的线程上生成事件。有一个很好的诊断方法,如果该工作线程不再存在,则会生成一个优先机会异常。您可以在“输出”窗口中看到它。

或者,您创建另一个UI线程并在两个线程上都有表单。不可避免地,这些形式之一总是会在错误的线程上获取事件。

唯一的体面建议是要承认在工作线程上创建UI是火箭科学,微软也不知道如何正确地做。值得注意的是,.NET 1.x控件具有事件处理程序,当从错误的线程中调用该事件处理程序时,该事件处理程序仍然可以正常工作,它仅调用Control.Invalidate()。但这是在2.0时似乎已经丢失的知识,ToolStrip是good example。并且不要相信组件供应商会正确地做到这一点,特别是Infragistics并没有出色的声誉。不要这样

10-07 19:52
查看更多