查找创建控件的目标线程
- 使用“!threads”命令显示所有线程,获取UI线程号(STA的就一个)
- 使用“!<UI线程号>s”命令切换至UI线程
- 使用“!dumpstackobjects”显示线程堆栈上的所有对象,获取WindowsFormsSynchronizationContext对象的地址
- 使用“!do <synchronizationContext对象地址>”命令显示其数据结构,从成员destinationThreadRef获取指定了创建控件的目标线程的WeakReference对象的地址
- 使用“!dumpobject <WeakReference对象地址>”显示其数据结构,从成员m_handle获取创建控件的目标线程的句柄
- 使用“dd <目标线程的句柄> L1”命令显示此句柄中包含的线程地址
- 使用“!dumpobject <目标线程地址>”命令显示目标线程的数据结构,从成员m_ManagedThreadId获取目标线程的托管线程号
- 使用“?0n<托管线程号>”命令获取托管线程号的16进制数
- 再次使用“!threads”命令显示所有线程,将刚获取的托管线程号与ID栏匹配,获取左边栏的线程对应的序号
- 使用“~<线程序号>s”命令切换至此线程
- 使用“!clearstack”命令查看此线程的堆栈,看是在运行哪些代码
结论
控件只应在UI线程上创建
参考
Debugging
Windows Forms Application Hangs During
SystemEvents.UserPreferenceChanged
Windows Forms application freezes when system settings
are changed or the workstation is locked