【问题标题】:WPF: How do I prevent tearing with WriteableBitmap?WPF:如何使用 WriteableBitmap 防止撕裂?
【发布时间】:2023-03-12 09:35:01
【问题描述】:

我正在使用 WriteableBitmap 以每秒 20 帧左右的速度显示我自己处理的图像。

这个问题(WPF: More efficient way of displaying quickly-changing images?
还有这个问题 (How to display quick-updating images without large memory allocation?)
表明最好的方法是使用WriteableBitmap

WriteableBitmap 的文档表明在 UI 线程上调用 WritePixels() 会导致渲染线程重绘图像:

MSDN 文档:
UI 线程将内容写入后台缓冲区。渲染线程从前端缓冲区读取内容并将其复制到显存。使用更改的矩形区域跟踪后台缓冲区的更改。

当更新被发送到渲染线程时,渲染线程将更改的矩形从后缓冲区复制到前缓冲区。渲染系统控制这种交换以避免死锁和重绘工件,例如“撕裂”。

我在后台线程上处理我的图像,然后使用Dispatcher.BeginInvoke() 调用WritePixels(),以确保在UI 线程上调用WritePixels()

我发现WriteableBitmap 仍然会出现撕裂现象,并且在我正在开发的应用程序中,它看起来很糟糕(它是一个医学成像应用程序)。有什么我可以做的吗?

【问题讨论】:

  • 这么多年过去了……你解决了这个问题吗?
  • @qakmak,很难回忆起这么久,但我相信转向更现代的操作系统是答案。查看接受的答案。
  • 这个答案对我来说不够好。但还是谢谢你
  • 不幸的是,不确定您是否会得到比这更好的答案。所有迹象都表明这是一个操作系统级别的问题。

标签: c# wpf .net-3.5 artifacts tearing


【解决方案1】:

我知道这是一个旧线程,但我们遇到了完全相同的问题,在我们的例子中,它是由使用 Dispatcher.BeginInvoke 调用我们的更新显示方法引起的 - 当我们更改为 Dispatcher.Invoke 时,它​​立即清除了。

【讨论】:

    【解决方案2】:

    为了避免撕裂,WriteableBitmap 做了很多工作,但在某些系统配置上,这是不可避免的。这主要发生在关闭 Aero (DWM) 的 Windows XP 或 Vista 上。

    【讨论】:

    • 我们在 Windows XP 上运行。我从来没有想过操作系统是问题所在,但这完全有道理——我在家里写的有趣的 WPF 应用程序在 Vista 和 Windows 7 上运行的数量级比在 XP 上好几个数量级。只是出于好奇,你是怎么知道的?
    • 我在 WPF 中对视频做了很多工作,所以一些知识只是随着领域和手掌而来。不知道技术原因是什么,但带 Aero 的 Vista 确保(大部分)您的 WPF 应用程序以与您的视频卡相同的赫兹绘制,因此不会撕裂。 XP 似乎会受到影响,具体取决于视频卡和驱动程序。许多人认为 Aero/DWM 会降低计算机速度,但这是不正确的。它极大地阻碍了性能。
    【解决方案3】:

    当您调用 WritePixels() 时,您可能正在覆盖您的位图。使用 Dispatcher.Invoke() 而不是 BeginInvoke() 可能会有所帮助。

    【讨论】:

    • 我同意。 BeginInvoke() 是异步的。使用 Invoke() 它应该可以很好地同步(尽管您可能会注意到延迟)。
    • 没有骰子 - 使用 Invoke() 而不是 BeginInvoke() 时同样的撕裂 :-(
    • WritePixels 应该锁定后台缓冲区,以防止渲染线程将部分后台缓冲区复制到前台缓冲区(因此导致撕裂)。 BeginInvoke 与 Invoke 不应该根据 WritePixels 的记录行为有所不同。
    猜你喜欢
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2012-06-15
    相关资源
    最近更新 更多