【发布时间】:2010-12-15 15:33:58
【问题描述】:
通常当我覆盖 OnPaint 方法时,我会在其中创建钢笔和画笔等,然后将它们处理掉。
我还在某处读到,不是重新创建这些钢笔和画笔等,而是将它们创建为静态成员一次,然后在表单关闭时处理它们一次,等等。
这是更好的做法吗?
有没有更好的方法?
我可以假设,由于 OnPaint 被调用了 1000 次(?)次,与只创建一次相比,这将为 GC 创建大量工作。
【问题讨论】:
通常当我覆盖 OnPaint 方法时,我会在其中创建钢笔和画笔等,然后将它们处理掉。
我还在某处读到,不是重新创建这些钢笔和画笔等,而是将它们创建为静态成员一次,然后在表单关闭时处理它们一次,等等。
这是更好的做法吗?
有没有更好的方法?
我可以假设,由于 OnPaint 被调用了 1000 次(?)次,与只创建一次相比,这将为 GC 创建大量工作。
【问题讨论】:
我上个月读到了interesting article,它建议将所有的绘画都放在一个单独的 BufferedGraphics 对象上,然后让 on_paint 方法从该对象直接复制到控件的图形对象。
这样,on-paint 速度更快,并且您仅在发生重大变化(即线条移动或文本更改)时才更新 BufferedGraphics。
【讨论】:
我真的取决于你在画什么。如果您要绘制仅由于用户交互而重新绘制的东西,您可以不必担心性能问题并临时创建所有图形对象,即在需要时。
确保您Dispose() 图形中所需的一切。钢笔、画笔、区域、字体。这些都是 GDI 对象,并通过 GDI 句柄绑定到系统中。
如果您需要以某种方式进行动画处理或无需用户点击即可及时更改的图形,请在前面准备好所有图形对象并尽可能多地重复使用它们。可以在这里应用的规则是,在绘制动画的每一帧时最好浪费内存而不是毫秒。
最后,至少在这篇文章中 - 不要忘记使用双缓冲,无论是在 .net 控制系统中自动还是回滚位图样式。
玩得开心 GDI :)
【讨论】:
我要做的是将画笔和钢笔作为自定义控件的成员,然后在处理控件时处理它们。这样,您每次调用 OnPaint 时都可以重复使用相同的画笔/笔。
我不会声明它们static,因为您无法知道何时可以处置您的物品。但正如 SLaks 所提到的,如果内存中同时有许多控件实例,最好将画笔和笔创建为静态的,这样在应用程序的生命周期内您只创建每个对象的一个实例.
【讨论】:
最佳做法是使用系统笔和画笔,因为它们已针对最少的资源消耗进行了优化。
【讨论】:
如果画笔和钢笔不改变,那么创建一次并重复使用它们肯定会更好。但是请注意,如果您的控件可能在多个线程上使用(这不太可能),您应该将它们设为 ThreadStatic(并在每个线程首次使用时初始化)或将它们设为实例成员(并将它们放置在控件的Dispose 覆盖);否则,您将得到不可重现的 GDI+ 错误,因为 GDI+ 对象不能同时在多个线程上使用。图像也是如此。
如果它们确实发生了变化(例如,如果您使用取决于控件大小的渐变画笔),您可能仍希望将它们存储在实例字段中,并在控件的大小(或其他)发生变化时重新创建它们。
注意,顺便说一下,如果你使用普通颜色,你可以使用静态的Brushes 和Pens 类,其中包含所有.Net 内置颜色的静态画笔和钢笔,以及SystemBrushes和SystemPens 用于系统颜色。
【讨论】:
Application.Run 调用结束时处理。
ShowDialog时,最好将代码包装在using语句中。