如何更快地使屏幕无效?

| 在我当前的项目(生活游戏)中,我需要重新绘制屏幕,​​因为大约有200个对象正在移动。我可以想到两种方法,但不知道会更快些: 我可以: 1)为整个屏幕调用Invalidate(),并且在Paint处理程序中具有以下内容:
void Paint(object sender, PaintEventArgs e)
{
   foreach(Cell c in ListOfCells)
          {
             e.DrawImage(c,c.x,c.y);
          }
}
2)或者我可以使每个单元格的屏幕各部分无效:
public void MyInvalidate()
{
  foreach(Cell c in ListOfCells)
              {
                 Invalidate(c.X,c.Y,c.Width,c.Height);
              }


}
并具有与上述相同的处理程序     
已邀请:
现在,第一个规则始终是“不要过早优化”。您需要确保需要对更干净的代码进行优化。 现在,在“人生游戏”中,您原来是在看一个非常空白的屏幕。但是,随着游戏的进行,越来越多的单元将被填充,最终整个面板将被填充。现在,GOL规则规定这些单元中的大多数将从一个循环更改为另一个循环。 您还需要了解“使区域无效”的含义。在Windows中,无效区域“加起来”形成一个“更新区域”,以便WM_PAINT消息可以告诉程序要绘制屏幕的哪一部分。在Paint事件处理程序中,使用ѭ2来确定是否要刷新单元格。 换句话说,执行方法1的“成本”(假设板尺寸为n):
(n x n) x (redraw cell + update cell on screen)
请注意,我假设您记得在绘制单元格之前要做一个清晰的屏幕,否则在上一个循环中曾经“处于活动状态”的单元格将保留在屏幕上。因此,这假设您正在整个屏幕上绘制活动单元格或空白单元格。 执行方法2的“费用”:
(v) x (redraw cell + update cell on screen) + (n x n) x (RectVisible call)
其中v =发生变化的单元数(请参见下面的注意事项)。 因此,在以下情况下,方法1比方法2更快。
(n x n) x redraw < v x redraw + (n x n) x RectVisible
n2 x (redraw - RectVisible) < v x redraw
v > ((redraw - RectVisible) / redraw) x n2
v > (1 - RectVisible/redraw) x n2
换句话说,已更改单元格的数量必须大于1减去(RectVisible成本/重绘成本)的比率。现在,与在屏幕上绘制位图相比,
RectVisible
通常相当快,尤其是在单元格为高分辨率的情况下。因此,Rectvisible / redraw通常是很小的数字,只有当同时有超过99%的电路板更换时,方法1才比方法2更快。 换句话说,您会发现方法2通常会产生更高的性能,因为如果要在剪切区域之外(即不在更新区域之内)绘制图像,ѭ7通常会跳过整个操作。 CAVEAT-无法使用您的代码 但是,您在方法2中的代码将无法正常工作。您必须记住要“清空”以前在最后一个循环中具有“活动”单元格的“死”单元格。换句话说,您使“更改”的单元无效,而不仅仅是使“活动”的单元无效。多个周期处于“活动状态”的单元格不需要无效。因此,您的
MyInvalidate
方法中的逻辑是有缺陷的。     
如果您坚持使用与第一个相同的Paint事件处理程序,那么第二个代码将无济于事,因为基本上您将多次重画所有单元格(因为每个单元格都会被重画其他所有单元格)。要解决此问题,您可以检查e.ClipRectangle,然后仅重绘该矩形内的单元格。 但是,如果屏幕上唯一的内容是单元格(因此您没有大量其他显示元素,例如UI控件),那么第一种方法就是最好的方法(即Invalidate()整个屏幕)。仅当您使屏幕上许多其他未更改的区域无效时,才会发生性能下降。     

要回复问题请先登录注册