【问题标题】:C#, WinForms Drawing data stored in an ArrayList. Is it a good idea?C#、WinForms 绘图数据存储在 ArrayList 中。这是个好主意吗?
【发布时间】:2011-11-23 14:37:15
【问题描述】:

在我的例子中,我有一个 2D ArrayList 对象,其中包含在绘制水平线、垂直线和填充矩形时使用的数据。在不同的情况下,对象的数量是不同的,图像中绘制的线条和矩形的数量也不同。但有时需要重新绘制图像。重绘的东西越多,屏幕上的闪光就越强(我希望你能明白我所说的“闪光”是什么意思)。

我已经尝试过双缓冲,但我认为我做得不对 - 闪光灯的类型只会改变......但这不是目前的情况。

我读到从 ArrayList 的任何位置添加和删除元素(无论类型如何)都很容易,但很难访问它们。我还读到 List 比 ArrayList 性能更好(这是否意味着程序将需要更少的计算机资源?),但从最后添加和删除元素很容易。但我不确定 Array 的性能是否是最快的。这让我觉得如果我用 Array 或 List 更改 ArrayList,闪光会变弱。

在我的情况下不会有问题,因为我存储在 ArrayList 中的所有元素都是同一个类。

我的问题是:如果我将 ArrayList 替换为 Array 或 List 是否可以削弱闪光?

【问题讨论】:

    标签: c# arrays winforms list arraylist


    【解决方案1】:

    好的,这里有两个问题。 ArrayList 与 List 的问题对“闪烁”没有影响,因为性能差异很小。如果您的列表项都是相同的类型,或者它们都派生自 object 以外的公共基本类型,或者它们都实现了公共接口,那么 List<T> 是更好的选择。这是因为涉及较少的铸件甚至装箱/拆箱。此外,您可以更轻松地访问您的项目。

    闪烁:在(您的表单或某些控件的)绘制事件方法中完成所有绘图。然后调用此窗体或控件的Invalidate 方法。不要“直接”绘制。作为一项改进,您可以将一个矩形结构传递给 Invalidate,以告知必须重绘哪个部分。在paint 方法中,您可以检查e.ClipRectangle,它告诉您必须重绘哪个部分。这使您有机会在这里进行一些改进。但是,请注意,Windows 操作系统本身可以触发 Invalidate,这会导致任意 ClipRectangles。

    【讨论】:

      【解决方案2】:

      比较绘图性能和从 ArrayList 读取性能,使用另一个数据容器无法解决闪烁问题。因此,ArrayList 的替代容器不是答案。您需要使用其他一些方法,例如;

      • 使用SDLDirectXOpenGL 之类的图形库。
      • 绘制到位图缓冲区并在完成后显示位图(类似于双缓冲,但有时效果更好)。
      • 子类化一些组件并覆盖一些方法,如背景绘制。

      还有更多的方法,但是你的问题的答案肯定和ArrayList没有太大关系。

      【讨论】:

      • 在某些情况下,对象的数量不仅仅是 2x2 或 4x3,而是 10x10 等等……(对于 NxM,我的意思是 N 阵列和 M 个元素。)并且矩形需要更多时间绘画。我所说的“削弱闪光”并不是指“停止闪光”,而是指如何使绘图更快。是的,我知道我必须处理双缓冲才能解决问题。但是如果让绘图速度更快(之后双缓冲会变得更快),应用程序也会变得更快。这是属于“必须做”列表的事情之一。
      • 我一直支持编写更好的优化代码,性能变化是否明显。但在您的情况下,在 1000x1000 次迭代中,您将获得大约 10-50 毫秒。想想与 10-50 毫秒相比,绘制 1000000 个矩形需要多长时间。 (见这里:dotnetperls.com/unboxing)。对于 int 类型的这些结果,我假设其他类型最多需要 5 倍的时间,并将迭代次数减少 100 倍。因此,我们都知道绘制 1000000 个矩形和类似的对象将花费大量时间。恕我直言,性能提升不会比 %0.1 高很多。
      【解决方案3】:

      您应该使用List<T> 而不是ArrayList,只是为了在您从列表中读取对象时摆脱不必要的强制转换。但是,与绘制图形相比,由此带来的性能提升非常小,因此不会对您的更新问题产生任何明显影响。

      您可以考虑将图形绘制成位图,然后在需要更新屏幕时绘制位图。


      List<T>ArrayList 在添加和删除元素时的行为相同;在列表末尾添加或删除元素很便宜,但在列表开头插入或删除元素更昂贵。

      数组是列表中最快的,List<T>ArrayList 都使用数组在内部存储其元素。但是,您无法调整数组的大小,因此您可能仍想使用 List<T>,因为它会根据需要分配数组并跟踪使用了多少数组。

      【讨论】:

      • List<T> 对于值类型来说要快得多。
      【解决方案4】:

      要修复“闪烁”,您需要启用双缓冲。

      您不应该使用 ArrayList,因为它会鼓励错误和/或糟糕的设计。
      您不应该有包含多种对象的列表。

      相反,您应该使用List<T>,也许与多态基类一起使用。

      【讨论】:

        猜你喜欢
        • 2011-12-03
        • 2010-10-30
        • 1970-01-01
        • 2015-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多