Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF UI在WaitOne之后挂起,dispatcher继续处理其他消息,并且不返回控制_C#_.net_Wpf_Freeze - Fatal编程技术网

C# WPF UI在WaitOne之后挂起,dispatcher继续处理其他消息,并且不返回控制

C# WPF UI在WaitOne之后挂起,dispatcher继续处理其他消息,并且不返回控制,c#,.net,wpf,freeze,C#,.net,Wpf,Freeze,在过去的几周里,我和我的团队一直在为一个UI挂起的问题挠头。从用户的角度来看,用户界面中的一个窗口在使用了很多小时后,偶尔会出现无响应的情况,即挂起。通常,用户界面线程中会出现死锁,但这里的情况并非如此。我们从这些事件中收集了一些挂起转储,并且总是看到相同的模式,即使在代码中的相同位置。我将尝试从高层次描述我们所看到的: 我们的UI代码在一个主UI线程上调用AutoResetEvent.WaitOne(超时)(下面将详细介绍) 注意:WPF中的WaitOne并不会真正阻止线程,但调度器可能会在

在过去的几周里,我和我的团队一直在为一个UI挂起的问题挠头。从用户的角度来看,用户界面中的一个窗口在使用了很多小时后,偶尔会出现无响应的情况,即挂起。通常,用户界面线程中会出现死锁,但这里的情况并非如此。我们从这些事件中收集了一些挂起转储,并且总是看到相同的模式,即使在代码中的相同位置。我将尝试从高层次描述我们所看到的:

  • 我们的UI代码在一个主UI线程上调用AutoResetEvent.WaitOne(超时)(下面将详细介绍)
  • 注意:WPF中的WaitOne并不会真正阻止线程,但调度器可能会在等待等待条件实现的同时处理Windows消息和其他可能的操作
  • WaitOne调用上方的调用堆栈显示了一系列HwndSource.LayoutFilterMessage->HwndSource.Process\u WM\u SIZE->ContextLayoutManager.UpdateLayout,然后是大量与WPF相关的调用(可能是调整代码大小)
  • 挂起时,进程使用大约一个CPU内核,这表明它正在持续处理,而不是死锁意义上的“挂起”
  • 有时挂起的情况会在几分钟内解决,UI将继续正常运行,但有时即使在30分钟后,UI仍然挂起(我们没有尝试让它运行一整晚,看看它是否总是恢复)
  • 在几次事件中,我们进行了多次挂起转储,虽然调用堆栈的顶部发生了一些变化,但HwndSource.LayoutFilterMessage始终存在(下面的所有内容都保持不变),阻止执行流返回到dispatcher对象,并随之返回到我们自己的代码
  • 我们的应用程序中挂起的窗口看起来是冻结的,它没有移动、振荡等等
下面是其中一个事件的堆栈跟踪。请注意,我删除了一块重复和递归的WPF调用,以缩短堆栈,并缩短了几个超宽参数列表。我还“匿名”了我们自己代码的类型名称

OS Thread Id: 0x3964 (38)
IP Call Site
MS.Internal.UIElementHelper.InvalidateAutomationAncestors(System.Windows.DependencyObject)
System.Windows.UIElement.Arrange(System.Windows.Rect)
System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size)
System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
System.Windows.UIElement.Arrange(System.Windows.Rect)
MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement, System.Windows.Size)
System.Windows.Controls.ContentPresenter.ArrangeOverride(System.Windows.Size)
System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
System.Windows.UIElement.Arrange(System.Windows.Rect)
System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size)
System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
System.Windows.UIElement.Arrange(System.Windows.Rect)
System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size)
... I removed about 50 lines of similar WPF calls ...
System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
System.Windows.UIElement.Arrange(System.Windows.Rect)
System.Windows.ContextLayoutManager.UpdateLayout()
System.Windows.Interop.HwndSource.Process_WM_SIZE(System.Windows.UIElement, IntPtr, MS.Internal.Interop.WindowMessage, IntPtr, IntPtr)
System.Windows.Interop.HwndSource.LayoutFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int64, Int32, Int64, Int64)
[InlinedCallFrame: 0000004e3d37abf8] MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
[InlinedCallFrame: 0000004e3d37abf8] MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr, Int32, IntPtr, IntPtr)
DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int64, Int32, Int64, Int64)
[InlinedCallFrame: 0000004e3d37af28] MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
[InlinedCallFrame: 0000004e3d37af28] MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int64, Int32, Int64, Int64)
[HelperMethodFrame_1OBJ: 0000004e3d37bc18] System.Threading.SynchronizationContext.WaitHelper(IntPtr[], Boolean, Int32)
... below is our code that calls WaitOne(timeout), above you can see the dispatcher handling a Windows resize message ...
System.Windows.Threading.DispatcherSynchronizationContext.Wait(IntPtr[], Boolean, Int32)
[GCFrame: 0000004e3d37c3c0] 
[HelperMethodFrame_1OBJ: 0000004e3d37c5b8] System.Threading.WaitHandle.WaitOneNative(System.Runtime.InteropServices.SafeHandle, UInt32, Boolean, Boolean)
System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean)
OurProduct.DataAccessService.WaitForReply(System.String) 
OurProduct.DataAccessService.GetPersonalRecipientGroup(Int32, Int32, System.Object)
OurProduct.NotificationTemplateSnapIn.MessageEditorSelection(OurProduct.SnapInNotificationData) 
OurProduct.NotificationTemplateSnapIn.NotificationTemplateSnapIn.Notify(OurProduct.SnapInNotificationData) 
OurProduct.SnapInHost.Notify(OurProduct.SnapInNotificationData) 
OurProduct.WindowConsole.SendSelectionMessage(...)
OurProduct.WindowConsole.Route(...) 
OurProduct.WindowConsole.ProcessMessage(...) 
OurProduct.SnapInHost.OnRaiseSnapInNotifyEvent(..)
OurProduct.SnapInBase.ExecuteSnapInNotify(...)
[DebuggerU2MCatchHandlerFrame: 0000004e3d37d190] 
[HelperMethodFrame_PROTECTOBJ: 0000004e3d37d4a8] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])
System.Delegate.DynamicInvokeImpl(System.Object[])
System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
System.Windows.Threading.DispatcherOperation.InvokeImpl()
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
System.Windows.Threading.DispatcherOperation.Invoke()
System.Windows.Threading.Dispatcher.ProcessQueue()
System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int64, Int32, Int64, Int64)
[InlinedCallFrame: 0000004e3d37e248] MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
[InlinedCallFrame: 0000004e3d37e248] MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
DomainBoundILStubClass.IL_STUB_PInvoke(System.Windows.Interop.MSG ByRef)
System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
OurProduct.App.ApplicationWindowThreadProcedure(System.Object) 
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
System.Threading.ThreadHelper.ThreadStart(System.Object)
[GCFrame: 0000004e3d37e9d8] 
[DebuggerU2MCatchHandlerFrame: 0000004e3d37ed28] 

关于我们的应用程序,我还想提一件事,不确定它是否重要:在运行时,它有多个窗口,每个窗口都有自己的UI线程。调用堆栈底部的App.ApplicationWindowThreadProcedure方法是该机制的一部分,用于使用每个窗口自己的调度程序和UI线程启动每个窗口。这也是UI中的其他窗口仍然响应的原因

我们发现了一个听起来非常相似的WPF错误报告:

然而,从所有我们可以看出,我们没有面临完全相同的问题(例如,CTRL-ALT-DEL技巧不起作用)。除此之外,我们在网上找不到其他类似的报道

总而言之,我认为WPF的HwndSource.LayoutFilterMessage方法要么返回很长的延迟,要么永远不会返回,这会阻止我们的代码在WaitOne调用的等待条件满足后继续处理。接下来的问题是,为什么它不回来,有没有办法让它回来,或者一开始就阻止它被调用。我很想给出一个最小的代码示例来重现这个问题,但不幸的是我们没有这个示例(否则我们现在可能已经自己解决了这个问题)


非常感谢你的帮助

“在运行时,它有多个窗口,每个窗口都有自己的UI线程”…为什么?我们的产品建立在内部开发的UI框架之上。据推测,这是为了利用多核和并行处理,因为其中一些窗口可能会执行一些繁重的UI工作,如视频和图像相关操作。在我们的挂起案例中,其他具有自己UI线程的窗口是打开的,但没有进行任何值得注意的处理。找到解决方案了吗?我也有同样的问题。mfc/bcg中嵌入的WPF控件,在本地上下文菜单打开时单击WPF控件中的元素后,UI将挂起。调度员在完成某项任务后很忙。主要应用是全功能tho。所有事件/命令和viewmodel仍在工作。但是我可以通过按键盘上的键来“释放”用户界面。在那之后,WPF又恢复了功能。哇,那是很久以前的事了;-)不幸的是,我不记得我们是否曾经解决过这个问题,我也不再和当时的人合作了。很抱歉