【问题标题】:Proper way around lengthy onPaint event in C# winforms?在 C# winforms 中解决冗长的 onPaint 事件的正确方法?
【发布时间】:2018-05-29 14:06:12
【问题描述】:

我目前正在开发一个 C# winforms 图形应用程序。为了切入正题,我的图形控件的 Paint 事件处理程序必须绘制数千个点,这可能需要几秒钟。在此期间,应用程序被冻结。我的目标如下:如果用户在绘制旧数据时更改了要绘制的数据,那么它将在绘制旧数据的过程中停止并开始绘制新数据。这样做的正确方法是什么,或者这是我完全想念的其他东西?我试图使我的问题尽可能清楚。

【问题讨论】:

  • 看看将你的绘图事件放在Task.Run 中,通过CancellationToken 并检查任务是否在你的绘图循环中被取消。如果用户更新数据,则触发您的取消令牌并使用新数据重绘。该任务将阻止您的应用程序锁定。
  • 最好(假设您使用图像/位图)在不同的线程上绘制图像,完成后,将其发送到主线程并将其添加到您的图片框
  • 您可以通过创建与显示相同大小的单独位图并从后台线程绘制到该位图来进行双缓冲,然后使用Graphics.DrawImage()绘制图像(从UI线程)完成。 (它比这更繁琐,但这就是它的要点。)
  • 您可以将较旧的 (1000s) 点缓存在位图中,并仅绘制最新的 (100s) 点。如果真的有必要,你甚至可以在一个单独的线程中准备位图。
  • @TaW 这听起来可以解决我的很多问题。谢谢!如果不是很麻烦,您能否发布一个关于如何创建位图图像然后用它更新 UI 线程的简单示例?

标签: c# winforms


【解决方案1】:

您的问题的答案在于双缓冲。您无需了解有关双缓冲的所有详细信息即可使用它。只需将属性设置为 true,如下所示即可在控件中启用它。

 MyGraphPanelControl.DoubleBuffered = true;

明显的缺点是内存使用,但它会大大提高在面板上绘制的“速度”。就像计算机科学中的很多事情一样,你用内存换取速度,反之亦然。

此外,阅读来自 Microsoft 的 this 将使您更深入地了解如何使用双缓冲。

【讨论】:

  • 启用双缓冲不会阻止 UI 线程在渲染发生时被阻塞。这只是意味着在整个渲染操作完成之前,渲染的结果是不可见的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多