我正在开发一个通常全天候运行的应用程序。它在一段时间内表现良好,但我注意到在DisplaySettingsChanging事件触发(通过RDP连接)后,应用程序将继续在后台处理,但UI变得完全无法使用。它没有在任务管理器中告诉您应用程序没有响应,就像UI消息泵被阻止一样。我知道SystemEvents类有一个错误(仍然在.NET 4中?)。我已将我们的启动画面移动到表单加载事件处理程序中,并且不在主UI线程以外的其他线程上创建任何控件。我已经尝试在我的主窗体的构造函数中订阅以下事件(它具有有效的SynchronizationContext)
SystemEvents.DisplaySettingsChanging
SystemEvents.DisplaySettingsChanged
SystemEvents.UserPreferencesChanged
但是按this related solution但似乎没有帮助。
我还缺少什么?
编辑1:运行spy ++后,我看到有两个线程拥有除主UI线程以外的Windows。但是,当我在visual studio中检查我的进程中的线程时,我看不到任何一个。这是否意味着一些引用的汇编是罪魁祸首?可能应该是一个单独的问题,但我怎么知道呢?
编辑2:第二个窗口是一个按钮单击事件,它打开一个打开的文件对话框。我检查了该线程的公寓状态,这是正确的STA。我还没有确定如何或何时创建其他线程。好像它一定是犯罪者。
答案 0 :(得分:2)
肯定是SystemEvents死锁。我在debugging using windbg的博客上找到了很多帮助。底部部分最有助于识别在不同的线程上创建哪些控件......并且有很多违规者。主要是在共享程序集中创建启动屏幕和许可证检查。无论如何,我认为我会在发现哪些控件导致问题时包含最有用的部分。
对我而言,就像这样
在windbg中打开可执行文件
运行,然后中断执行并在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) < / p>
bp 7fedf04a440“.echo MarshalingControl创建被检测到.Callstack跟随。;!clrstack; .echo ============================= =; gc“(设置断点以在调用该构造函数时输出callstack)
我还在SynchronizationContext上使用了这个article的概念来实际实现解决方案。