【问题标题】:Winforms UI hang after DisplaySettingsChangingeventWinforms UI 在 DisplaySettingsChangingevent 后挂起
【发布时间】:2015-10-21 15:27:01
【问题描述】:

我正在开发一个通常 24x7 运行的应用程序。它在一段时间内表现良好,但我注意到在 DisplaySettingsChanging 事件触发(通过 RDP 连接)后,应用程序将继续在后台处理,但 UI 变得完全无法使用。它不会在任务管理器中告诉您应用程序没有响应,就像 UI 消息泵被阻止时一样。我知道 SystemEvents 类存在错误(仍在 .NET 4 中?)。我已将初始屏幕移到表单加载事件处理程序中,并且不在主 UI 线程之外的另一个线程上创建任何控件。我尝试在主窗体的构造函数中订阅以下事件(它具有有效的 SynchronizationContext)

SystemEvents.DisplaySettingsChanging 
SystemEvents.DisplaySettingsChanged
SystemEvents.UserPreferencesChanged

但根据this related solution,但它似乎没有帮助。

我还缺少什么?

编辑 1:运行 spy++ 后,我看到有两个线程拥有除主 UI 线程之外的窗口。但是,当我在 Visual Studio 中检查我的进程中的线程时,我看不到任何一个。这是否意味着某些引用的程序集是罪魁祸首?可能应该是一个单独的问题,但我该如何找到?

编辑 2:第二个窗口是一个按钮单击事件,它打开一个打开的文件对话框。我检查了该线程的公寓状态,它是正确的 STA。我尚未确定如何或何时创建该其他线程。看来一定是犯人了。

【问题讨论】:

  • 嗯,不,这无疑是由 SystemEvents 类引起的标准死锁。它没有错误,只是很难找出 some 程序中哪个线程是 UI 线程。设置定时炸弹只需要一个表单,尤其是在 VB.NET 中,当您使用可怕的 My.Forms feature 时。你可以盯着这样的代码看一个小时,却看不到表单实际上是在工作线程上创建的。继续寻找,它就在某个地方。 ShowDialog() 最擅长隐藏它。

标签: .net vb.net multithreading winforms .net-4.0


【解决方案1】:

这肯定是 SystemEvents 死锁。我从一些资源中找到了很多帮助,主要是debugging using windbg 上的这个博客。底部部分最有助于确定哪些控件是在单独的线程上创建的......并且有很多违规者。主要在创建启动屏幕和许可证检查的共享程序集中。无论如何,我认为我会在发现哪些控件导致问题时包含最有用的部分。

对我来说是这样的

  1. 在windbg中打开可执行文件

  2. 运行,然后中断执行并在 windbg 中运行这些命令

.sympath srv*http://msdl.microsoft.com/download/symbols (加载 MS 符号)

.reload (重新加载模块)

.loadby sos.dll clr(加载帮助模块)

!name2ee System_Windows_Forms_ni System.Windows.Forms.Application+MarshalingControl..ctor (获取将控件的构造函数编组到另一个线程的指针,然后返回该位置的指针。在我的例子中是 7fedf04a440)

bp 7fedf04a440 "检测到.echo MarshalingControl 创建。调用堆栈跟随。;!clrstack;.echo ============================= =;gc" (设置断点以在调用该构造函数时输出调用堆栈)

我还在 SynchronizationContext 上使用了来自 article 的概念来实际实施解决方案。

【讨论】:

    猜你喜欢
    • 2017-04-27
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    • 2014-06-23
    • 1970-01-01
    • 2013-03-04
    相关资源
    最近更新 更多