WPF 中的屏幕截图不包含所有 UI 更新

sti*_*ijn 6 c# wpf screenshot

我使用的代码这样做在WPF应用程序屏幕截图。简而言之:

var drawingvisual = new DrawingVisual();
using( DrawingContext context = drawingvisual.RenderOpen() )
{
  context.DrawRectangle( new VisualBrush( fooElement ), null, new Rect( fooElementSize ) );
  context.Close();
}
var r = new RenderTargetBitmap( ... );
r.Render( drawingvisual );
SaveBitmapToFile( r, .... );
Run Code Online (Sandbox Code Playgroud)

该原理工作得很好,例如在单击鼠标时调用时,但我在以编程方式调用它时遇到了问题。流程是:

  • 后台线程想要更​​新 UI 并使用 Application.Current.Dispatcher.Invoke
  • 后台线程做其他事情(这只需要一些毫秒)
  • 后台线程向它刚刚更新的 UI 的同一部分发出命令,再次使用 Application.Current.Dispatcher.Invoke

这在我的开发机器上工作正常,但在某些用户的机器上,这会导致保存的图像不包含所有更新。因此,例如,当 TextBlock 具有文本“running”并且上面的第一步将其设置为空字符串时,屏幕截图仍显示 TextBlock 的“running”。或者,如果第一步包括用一堆元素填充 Canvas,屏幕截图只是不包括它们。当要渲染的元素隐藏在其他窗口等后面时,情况也会变得更糟。

考虑到这一点,似乎关键问题是 WPF 使用单独的渲染线程,并且只有当该线程完成其工作时,UI 才会真正绘制并准备好捕获。四处搜索会产生一些点击,甚至一些“解决方案”围绕......

Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.ApplicationIdle,
  new Action( () => { } ) ).Wait();
Run Code Online (Sandbox Code Playgroud)

...但据我所知,这只是等到 UI 线程空闲,这并不能保证渲染线程已完成更新我想要捕获的 UI 部分?无论如何,在捕获代码之前在后台线程中插入这一行没有任何区别。有时似乎有效的方法只是将后台线程阻塞 100 毫秒左右,然后进行捕获。但这只是解决方案的一半。

我在做什么有什么问题吗,可以更改什么以确保捕获的图像始终包含 UI 的最新更新?