在关闭时更改桌面布局的windows form application中,Windows窗体在处理WM_SETTINGCHANGE
消息时似乎挂起。这似乎发生在应用程序关闭开始和结束之间收到的任何WM_SETTINGSCHANGE
消息。
除了添加任意延迟之外,还有什么方法可以避免这种挂起?
事件的明显时间轴:
1.在主线程上,在关闭唯一的窗体时,会触发对桌面布局的更改(特别是由于使用SHAppBarMessage(ABM_REMOVE, ...)
删除AppBar)
1.主线程开始关闭(释放控件、窗体等)
1.“.NET系统事件”线程接收WM_SETTINGCHANGE
并返回到主线程
1.由于主线程没有关闭,WindowsFormsSynchronizationContext.Send:82
测试成功
1.“.Net System Events”线程进入WaitHandle
1.主线程关闭了主窗体,退出消息循环,Main
返回
1.挂
挂起时的调用堆栈:
主线程(无.Net堆栈,仅限本机)
win32u.dll!NtUserMsgWaitForMultipleObjectsEx()
combase.dll!CCliModalLoop::BlockFn(void * * ahEvent, unsigned long cEvents, unsigned long * lpdwSignaled) Line 2108
combase.dll!ClassicSTAThreadWaitForHandles(unsigned long dwFlags, unsigned long dwTimeout, unsigned long cHandles, void * * pHandles, unsigned long * pdwIndex) Line 54
combase.dll!CoWaitForMultipleHandles(unsigned long dwFlags, unsigned long dwTimeout, unsigned long cHandles, void * * pHandles, unsigned long * lpdwindex) Line 126
[Inline Frame] hostpolicy.dll!coreclr_t::shutdown(int *) Line 152
hostpolicy.dll!run_app_for_context(const hostpolicy_context_t & context, int argc, const wchar_t * * argv) Line 264
...snip...
.NET系统事件线程
System.Private.CoreLib.dll!System.Threading.WaitHandle.WaitOneNoCheck(int millisecondsTimeout) Line 139
at /_/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs(139)
System.Windows.Forms.dll!System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle waitHandle) Line 3967
at /_/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs(3967)
System.Windows.Forms.dll!System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control caller, System.Delegate method, object[] args, bool synchronous) Line 7141
at /_/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs(7141)
System.Windows.Forms.dll!System.Windows.Forms.Control.Invoke(System.Delegate method, object[] args) Line 6587
at /_/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs(6587)
System.Windows.Forms.dll!System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback d, object state) Line 88
at /_/src/System.Windows.Forms/src/System/Windows/Forms/WindowsFormsSynchronizationContext.cs(88)
Microsoft.Win32.SystemEvents.dll!Microsoft.Win32.SystemEvents.SystemEventInvokeInfo.Invoke(bool checkFinalization, object[] args) Line 35
at Microsoft.Win32\SystemEvents.cs(35)
Microsoft.Win32.SystemEvents.dll!Microsoft.Win32.SystemEvents.RaiseEvent(bool checkFinalization, object key, object[] args) Line 850
at Microsoft.Win32\SystemEvents.cs(850)
locals:
array[0]
._delegate = System.Windows.Forms.VisualStyles.VisualStyleRenderer.OnUserPreferenceChanging
._syncCtx = System.Windows.Forms.WindowsFormsSynchronizationContext
Microsoft.Win32.SystemEvents.dll!Microsoft.Win32.SystemEvents.WindowProc(nint hWnd, int msg, nint wParam, nint lParam) Line 961
at Microsoft.Win32\SystemEvents.cs(961)
locals:
msg = 8218
wParam = 0x2f
lParam = 0
[Native to Managed Transition]
[Managed to Native Transition]
Microsoft.Win32.SystemEvents.dll!Interop.User32.DispatchMessageW.____PInvoke|210_0(Interop.User32.MSG* msg)
Microsoft.Win32.SystemEvents.dll!Microsoft.Win32.SystemEvents.WindowThreadProc() Line 1038
at Microsoft.Win32\SystemEvents.cs(1038)
备注:
- 没有在后台线程上创建控件(Debugging Windows Forms Application Hangs During SystemEvents.UserPreferenceChanged不适用)
- 标签:WinForms application hang due to SystemEvents.OnUserPreferenceChanged event
- 已打开的问题:Hang during exit if WM_SETTINGCHANGE is received
- 表单上至少需要一个控件(以通过
VisualStyleRenderer..cctor
创建SystemEvents.UserPreferenceChanging
) - Repro with
SHAppBarMessage
和memory dump - Minimal repro with
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, ...)
1条答案
按热度按时间gab6jxml1#
此was a bug在.Net中从.Net 5到.Net 7.0.11。.Net Framework不受影响。要解决这个问题,请至少升级到.Net 7.0.12或使用下面的
PostQuitMessage
黑客。使用自定义的
ApplicationContext
,确保SystemEvents
线程在退出前当前未挂起: