title: WPF UI thread freezes momentarily when a mouseup event triggers an animation
body: <p>I have a WPF application that is constantly animating. One interaction (mouseup) and animation in particular seems to freeze the UI thread for long enough to be very noticable.</p>
  
  <p>Concurrency Visualizer shows me my UI thread is blocked for 300 - 500ms. It also shows the stack while it's blocked and the unblocking stack:</p>
  
  <p><strong>Main thread stack while frozen</strong>:<br>
  Category = Synchronization<br>
  Delay = 495.2472 ms  </p>
  
  <pre><code>ntoskrnl.exe!SwapContext_PatchXRstor
  ntoskrnl.exe!KiSwapContext
  ntoskrnl.exe!KiCommitThreadWait
  ntoskrnl.exe!KeWaitForSingleObject
  ntoskrnl.exe!NtWaitForSingleObject
  ntoskrnl.exe!KiSystemServiceCopyEnd
  ntdll.dll!NtWaitForSingleObject
  kernelbase.dll!WaitForSingleObjectEx
  wpfgfx_v0400.dll!CMilConnection::SynchronizeChannel
  wpfgfx_v0400.dll!CMilChannel::SyncFlush
  wpfgfx_v0400.dll!MilComposition_SyncFlush
  clr.dll!DoNDirectCallWorker
  presentationcore.dll!System.Windows.Media.Composition.DUCE+Channel.**SyncFlush**
  presentationcore.dll!System.Windows.Media.MediaContext.NotifyChannelMessage
  presentationcore.dll!System.Windows.Media.MediaContextNotificationWindow.MessageFilter
  windowsbase.dll!MS.Win32.HwndWrapper.WndProc
  windowsbase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation
  windowsbase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall
  windowsbase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen
  windowsbase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke
  windowsbase.dll!System.Windows.Threading.Dispatcher.InvokeImpl
  windowsbase.dll!MS.Win32.HwndSubclass.SubclassWndProc
  windowsbase.dll!dynamicClass.IL_STUB_ReversePInvoke
  clr.dll!UMThunkStubAMD64
  user32.dll!UserCallWinProcCheckWow
  user32.dll!DispatchMessageWorker
  clr.dll!DoNDirectCall__PatchGetThreadCall
  windowsbase.dll!dynamicClass.IL_STUB_PInvoke
  windowsbase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl
  presentationframework.dll!System.Windows.Application.RunInternal
  presentationframework.dll!System.Windows.Application.Run
  xqstream.windows.exe!IQ.IR.Stream.WPF.App.Main
  </code></pre>
  
  <p><strong>Unblocking Stack:</strong></p>
  
  <pre><code>ntoskrnl.exe! ?? ?? ::FNODOBFM::`string'
  ntoskrnl.exe!NtSetEvent
  ntoskrnl.exe!KiSystemServiceCopyEnd
  ntdll.dll!ZwSetEvent
  kernelbase.dll!SetEvent
  wpfgfx_v0400.dll!CMilConnection::PostMessageToClient
  wpfgfx_v0400.dll!CMilServerChannel::SignalFinishedFlush
  wpfgfx_v0400.dll!CComposition::FlushChannels
  wpfgfx_v0400.dll!CPartitionThread::RenderPartition
  wpfgfx_v0400.dll!CPartitionThread::Run
  wpfgfx_v0400.dll!CPartitionThread::ThreadMain
  </code></pre>
  
  <p>The main thread is waiting on a background thread. That background thread is doing a number of things, but this stack takes up ~3/4 of the time:</p>
  
  <p><strong>Blocking thread's largest task:</strong>
  Category = I/O<br>
  Delay = 347.5122 ms  </p>
  
  <pre><code>ntoskrnl.exe!SwapContext_PatchXRstor
  ntoskrnl.exe!KiSwapContext
  ntoskrnl.exe!KiCommitThreadWait
  ntoskrnl.exe!KeWaitForSingleObject
  dxgmms1.sys!VIDMM_GLOBAL::CloseOneAllocation
  dxgmms1.sys!VidMmCloseAllocation
  dxgkrnl.sys!DXGDEVICE::DestroyAllocations
  dxgkrnl.sys!DXGDEVICE::ProcessTerminationList
  dxgkrnl.sys!DXGDEVICE::TerminateAllocations
  dxgkrnl.sys!DXGDEVICE::DestroyAllocation
  dxgkrnl.sys!DxgkDestroyAllocation
  win32k.sys!NtGdiDdDDIDestroyAllocation
  ntoskrnl.exe!KiSystemServiceCopyEnd
  gdi32.dll!ZwGdiDdDDIDestroyAllocation
  d3d9.dll!DeallocateCB
  dlumd64.dll![dlumd64.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  nvd3dumx.dll![nvd3dumx.dll]
  dlumd64.dll![dlumd64.dll]
  dlumd64.dll![dlumd64.dll]
  d3d9.dll!DdBltLH
  d3d9.dll!CSwapChain::PresentMain
  d3d9.dll!CSwapChain::Present
  wpfgfx_v0400.dll!CD3DDeviceLevel1::PresentWithD3D
  wpfgfx_v0400.dll!CD3DDeviceLevel1::Present
  wpfgfx_v0400.dll!CHwDisplayRenderTarget::PresentInternal
  wpfgfx_v0400.dll!CHwDisplayRenderTarget::Present
  wpfgfx_v0400.dll!CHwHWNDRenderTarget::Present
  wpfgfx_v0400.dll!CDesktopRenderTarget::Present
  wpfgfx_v0400.dll!CDesktopHWNDRenderTarget::Present
  wpfgfx_v0400.dll!CSlaveHWndRenderTarget::Present
  wpfgfx_v0400.dll!CRenderTargetManager::Present
  wpfgfx_v0400.dll!CComposition::Present
  wpfgfx_v0400.dll!CPartitionThread::PresentPartition
  wpfgfx_v0400.dll!CPartitionThread::Run
  wpfgfx_v0400.dll!CPartitionThread::ThreadMain
  </code></pre>
  
  <p>I've read SyncFlush() is called after several MilCore functions and appears to cause the changes that have been sent to be processed immediately (credit to Ray Burns). </p>
  
  <p>I'd like to get rid of this freeze, but I'm also hoping to develop a better understanding of what WPF is doing in this situation so that I can build a better mental model of how WPF works.</p>