title: WPF UI hangs after a WaitOne, dispatcher keeps processing other messages and does not return control
body: <p>For the past few weeks my team and I have been scratching our heads with a UI hang problem. From the user perspective, very sporadically and after many hours of use, one window in our UI becomes unresponsive, i.e. hangs. Typically, you would expect a deadlock in the UI thread but this is not the case here. We have collected hang dumps from several of these occurrences and always see the same pattern, even in the same place in our code. I will try to describe at a high level what we see:</p>
  
  <ul>
  <li>Our UI code calls AutoResetEvent.WaitOne(timeout) on one of the main UI threads (more on that below).</li>
  <li>Note: A WaitOne in WPF does not really block the thread but the dispatcher may process Windows messages and other possibly other operations while waiting for the wait condition to come true.</li>
  <li>The call stack above our WaitOne call shows a sequence of HwndSource.LayoutFilterMessage -> HwndSource.Process_WM_SIZE -> ContextLayoutManager.UpdateLayout and then a lots of WPF-related calls (presumably resizing code).</li>
  <li>While hung, the process uses approximately one CPU core, which indicates that it is continuously processing and not "hung" in the sense of a deadlock. </li>
  <li>Sometimes the hang situation will resolve within a few minutes and the UI will continue operating normally, but other times even after 30 minutes the UI is still hung (we have not tried to let it run over night to see if it always recovers).</li>
  <li>During several occurrences we have taken multiple hang dumps and while the top of the call stack changes somewhat, the HwndSource.LayoutFilterMessage is always there (and everything below remains the same), preventing the execution flow to return to the dispatcher object and with that to our own code.</li>
  <li>The hung window in our application just looks frozen, it is not moving around, oscillating or so.</li>
  </ul>
  
  <p>Below is the stack trace from one of those occurrences. Please note that I removed a block of repetitive and recursive WPF calls to shorten the stack, as well as shortened a few super-wide parameter lists. I also "anonymized" the type names of our own code.</p>
  
  <pre><code>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] 
  </code></pre>
  
  <p>There is one more thing I wanted to mention about our application, not sure if it matters: At runtime it has multiple windows, and each window runs with its own UI thread. The App.ApplicationWindowThreadProcedure method at the bottom of the call stack is part of this mechanism, to start each window with its own dispatcher and UI thread. This is also the reason why other windows in the UI are still responsive.</p>
  
  <p>We have found a WPF bug report that sounds very similar: <a href="https://connect.microsoft.com/VisualStudio/feedback/details/807292/wpf-application-intermittently-hangs-when-using-dispatcher-invoke-and-or-dispatcher-pushframe-while-user-is-resizing-or-draging-window" rel="nofollow">WPF application intermittently hangs when using Dispatcher.Invoke and/or Dispatcher.PushFrame while user is resizing or draging window</a></p>
  
  <p>However, from all we can tell we are not facing the exact same issue (e.g. The CTRL-ALT-DEL trick does not work). Besides this, we could not find any other similar report on the web.</p>
  
  <p>To summarize, I believe that WPF's HwndSource.LayoutFilterMessage method returns either with great delay, or never, and this prevents our code from continuing to process after the WaitOne call's waiting condition has been fulfilled. Then the next question is, why does it not return, and is there a way to make it return, or prevent it from being called in the first place. I would love to give a minimal code example that reproduces the issue but unfortunately we don't have that (otherwise we probably would have resolved the issue ourselves by now). </p>
  
  <p>Thank you very much for your help!</p>