.NET 4.0 和可怕的 OnUserPreferenceChanged Hang [英] .NET 4.0 and the dreaded OnUserPreferenceChanged Hang

查看:21
本文介绍了.NET 4.0 和可怕的 OnUserPreferenceChanged Hang的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直被可怕的 OnUserPreferenceChanged Hang 所困扰,Ivan Krivyakov 在这里很好地提到了它:

I have been plagued with the dreaded OnUserPreferenceChanged Hang that's refered to quite nicely by Ivan Krivyakov, here:

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

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

I posted a question a while back, when I originally encountered the problem:

又一个 C# 死锁调试问题

我以为我已经通过删除从 UI 线程构建的 Control 解决了这个问题,但过了一会儿它又出现了(可能从未离开过......).

I thought I had solved it by removing a Control that was constructed off the UI thread, but after a little while it reappeared (probably never left...).

我们一直在使用 .NET 3.5,据我所知使用的是 CLR 2.0.最近,应用程序已升级为使用 .NET 4.0 Client Profile/CLR 4.0.此外,我们已从 Infragistics WinForms 10.1 升级到 10.3.唯一的另一个区别是之前的版本被混淆了……有没有人遇到过混淆和挂起的问题?

We've been using .NET 3.5, which I understand uses CLR 2.0. Recently, the applciation has been upgraded to use .NET 4.0 Client Profile / CLR 4.0. In addition, we've upgraded from Infragistics WinForms 10.1 to 10.3. The only other difference is that the previous version is obfuscated... has anyone experienced issues with obfuscation and hanging?

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

I've had another stab at getting rid of any application hangs once and for all, but unusually, I have not been able to reproduce the hang in the most recent version (using .NET 4.0). The hang is simple to reproduce in the previous version (using .NET 3.5), using Ivan Krivyakov's handy Freezer application (see his article for it), which fires a WM_SETTINGCHANGE message upon request.

我可能有点希望问题会自行消失,但是有谁知道从 2.0 到 4.0 的 CLR 是否有任何更改会导致这种情况?

It may be me being a little hopeful that the issue has disappeared off it's own accord, but does anyone know if there have been any changes to the CLR from 2.0 to 4.0 that would cause this?

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

因此在测试应用程序的变体之后,例如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 或 CLR 4.0 和 Infragistics 2010.3 来重现冻结(我们现在已经非常擅长重现这个......).

So after testing variations of the application e.g. CLR 2.0 + Infragistics 2010.1, CLR 2.0 + Infragistics 2010.3 and CLR 4.0 + Infragistics 2010.1, we believe we've identified the problem to have been an issue with an Infragistics component in WinForms 2010.1 (no hot fixes). We still have yet to reproduce the freeze using either CLR 2.0 or CLR 4.0 with Infragistics 2010.3, instead (and we've gotten pretty good at reproducing this now...).

推荐答案

从 UI 线程构建的控件...

a Control that was constructed off the UI thread...

是的,这是触发此问题的好方法.底层问题是由 SystemEvents 类引起的,它具有在正确线程上引发其事件的令人讨厌的任务.UserPreferenceChanged 事件是典型的麻烦制造者,许多控件订阅它以便在用户更改桌面主题时可以重新绘制自己.组件供应商不会忽视对此的需求.工具箱中的标准 .NET 框架控件也没有.

Yes, that is a good way to trigger this problem. The underlying problem is caused by the SystemEvents class, it has the unenviable task of raising its events on the correct thread. The UserPreferenceChanged event is the typical trouble-maker, lots of controls subscribe it so they can repaint themselves when the user changes the desktop theme. A component vendor would not overlook the need for this. Nor do the standard .NET framework controls in the toolbox.

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

A usually decent way to test for this problem is to lock the workstation (press the Win+L keys), also the way the deadlock is commonly triggered on the user's machine. The switch to the secure desktop tends to trigger the event. With the additional quirks that this never happens when you debug your program and that it has tricky time-related behavior since this tends to happen when nobody is at the machine. Extra hard to debug.

遇到这种麻烦的一种标准方法是程序中的初始化问题.订阅的第一个 SystemEvents 事件会导致 SystemEvents 类初始化自身并设置接收这些通知和引发相应事件所需的管道.自定义启动画面做得太多(即不仅仅是显示位图)并在标记为 STA 的工作线程上运行,足以让这个错误发生.像 ProgressBar 这样简单的东西已经足够了.SystemEvents 假设工作线程是程序的主线程,现在可以轻松地在未来的错误线程上生成事件.对此有一个很好的诊断方法,如果该工作线程不再存在,则会生成第一次机会异常.您可以在输出"窗口中看到它.

One standard way to get into trouble like this is because of an initialization problem in the program. The very first SystemEvents event that is subscribed causes the SystemEvents class to initialize itself and setup the plumbing that's necessary to receive these notifications and raise their corresponding event. A custom splash screen that does too much (i.e. more than just display a bitmap) and runs on a worker thread that is marked as STA is enough to get this wrong. Something as simple as a ProgressBar is already enough. SystemEvents assumes that the worker thread is the main thread of the program and can now easily generate the events on the wrong thread in the future. There is one good diagnostic for this, if that worker thread is no longer around then that generates a first-chance exception. You can see it in the Output window.

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

Or you create another UI thread and have forms on both threads. Inevitably one of these forms is always going to get the event on the wrong thread.

唯一合适的建议是承认在工作线程上创建 UI 是一种火箭科学,微软也不知道如何正确地做.值得注意的是 .NET 1.x 控件有一个事件处理程序,当它从错误的线程调用时仍然可以正常工作,它只是调用 Control.Invalidate().但这些知识似乎在 2.0 中丢失了,ToolStrip 是一个 很好的例子.并且不要相信组件供应商能够做到这一点,尤其是 Infragistics 没有出色的声誉.不要这样做.

The only decent advice is to acknowledge that creating UI on a worker thread is rocket science that Microsoft did not know how to do correctly either. Notable is that the .NET 1.x controls have an event handler that still works correctly when it is called from the wrong thread, it merely call Control.Invalidate(). But that was knowledge that appears to have been lost at 2.0, ToolStrip is a good example. And do not trust a component vendor to get this right, Infragistics in particular does not have a stellar reputation. Don't do it.

这篇关于.NET 4.0 和可怕的 OnUserPreferenceChanged Hang的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆