简体   繁体   English

我应该为每个Paint请求创建新的Pens / Brushes还是在整个应用程序生命周期中保留它们?

[英]Should I create new Pens/Brushes per Paint request or keep them throughout the application lifecycle?

I have an application that does a lot of drawing, let's pretend it's a Viso-like application. 我有一个应用程序做了很多绘图,让我们假装它是一个类似Viso的应用程序。 It has objects that have multiple sub-objects that are drawn, things can be connected, resized etc. Currently when I call paint on a particular sub-object or object, I do the following: 它有一些对象,它们有多个绘制的子对象,可以连接的东西,调整大小等等。目前,当我在特定的子对象或对象上调用paint时,我会执行以下操作:

using(var pen = new Pen(this.ForeColor))
{
    // Paint for this object.
}

I've read conflicting answers that this should be done for an application that is constantly drawing the same thing (maybe just resized, moved etc). 我已经阅读了相互矛盾的答案,这应该为一个不断绘制相同内容的应用程序(可能只是调整大小,移动等)来完成。 Should I store the Pen/Brush with the object and then dispose them all when the application is disposed of, or are they efficient enough to be created/disposed for each paint call (remembering that this is a pretty graphics intense application). 我应该将Pen/Brush与对象一起存储,然后在处理应用程序时将它们全部丢弃,或者它们是否足够高效以便为每次绘制调用创建/处理(记住这是一个非常图形密集的应用程序)。

EDIT : There are already two answers that have conflicting answers and this is where I'm not sure to make the switch. 编辑 :已经有两个答案有相互矛盾的答案,这是我不确定要切换的地方。 Does anyone have any stats on the differences? 有没有人对这些差异有任何统计数据?

You could of course use the Pens and Brushes classes that provide you with objects that are already created by the runtime. 您当然可以使用Pens和Brushes类来为您提供已由运行时创建的对象。

For example, if you want one of the standard colour Pens , you can do this: 例如,如果您想要一个标准颜色 ,您可以这样做:

var pen = Pens.Red;

Likewise you can do the same with Brushes , if you just want standard solid brush colours: 同样,如果你只想要标准的实心画笔颜色,你可以用画笔做同样的事情:

var brush = Brushes.Red

Using these, you don't need to worry about cleaning them up, disposing it or otherwise. 使用这些,您无需担心清理,处理或其他方式。

If you want different colours that you create yourself, for example with a different alpha component, or a gradient brush perhaps, then you still need to create these yourself and clean them up appropriately. 如果您想要自己创建不同的颜色,例如使用不同的alpha组件或渐变画笔,那么您仍然需要自己创建并适当地清理它们。

EDIT: 编辑:

To create and dispose of an array of 100,000 new pens took approximately half a second on my ancient old XP machine, running a test app in Debug mode. 创建和处理一个由100,000个新笔组成的数组,在我古老的旧机器上花了大约半秒钟,在调试模式下运行测试应用程序。

That equates to approximately 5 microseconds per pen . 这相当于每笔约5微秒 Only you can decide if that is fast enough for you. 只有你可以决定它是否足够快。 I would hazard a guess that this time may be largely insignificant with regard to the rest of your operations. 我猜想这个时间对于你的其他行动来说可能是微不足道的。

You'll only know the performance impact by testing on your particular application, but the framework doesn't seem to have a problem keeping a few pens around for the life of the application. 您只会通过测试特定应用程序来了解性能影响,但是在应用程序的生命周期中保留一些笔似乎没有问题。 The first time you call Pens.Black , it creates a black pen and caches it. 第一次调用Pens.Black ,它会创建一个黑色笔并缓存它。 You get the same object back for future calls, and it's never explicitly disposed (Pens.Black.Dispose() will actually throw an exception). 对于将来的调用,您将获得相同的对象,并且它从未明确处理(Pens.Black.Dispose()实际上会抛出异常)。 However, you don't want to blindly create pens and leave them to be disposed when the application ends, because you'll be leaking unmanaged memory. 但是,您不希望盲目地创建笔并在应用程序结束时让它们被丢弃,因为您将泄漏非托管内存。 A couple of options spring to mind depending on the pattern of usage in your app. 根据应用程序中的使用模式,可以想到几个选项。

Give each object a private Pen that's created when ForeColor is set and reused for all painting. 为每个对象提供一个私人笔,该笔在设置ForeColor时创建,并重复用于所有绘画。 You should make your object IDisposable so that it can dispose of that Pen properly. 你应该使你的对象IDisposable,以便它可以正确处置该笔。

If you're using relatively few distinct colours but lots of objects use each colour, you may not want each object to hold on to its own Pen. 如果您使用相对较少的不同颜色,但许多对象使用每种颜色,您可能不希望每个对象都保留其自己的笔。 Create some cache class that keeps a Dictionary<Color,Pen> and hands them out through a PenCache.GetPen(ForeColor) . 创建一些保存Dictionary<Color,Pen>缓存类,并通过PenCache.GetPen(ForeColor)它们移出。 Like using Pens.Black, you can now forget about disposing them. 就像使用Pens.Black一样,你现在可以忘记处理它们了。 A problem arises if you use a colour briefly, then don't need it again. 如果您简单地使用颜色,然后再不需要它,则会出现问题。 The Pen got cached, so you're stuck with it in memory forever. Pen被缓存了,所以你永远坚持使用它。 You could keep a Dictionary<Color,WeakReference<Pen>> instead, allowing cached pens to be eventually garbage collected if they're no longer needed. 您可以保留Dictionary<Color,WeakReference<Pen>> ,允许缓存的笔最终被垃圾收集,如果它们不再需要的话。

That last option may be the best general purpose solution, avoiding gratuitous creation and disposal while letting the garbage collector make sure that orphaned pens don't cause too much memory trouble. 最后一个选项可能是最好的通用解决方案,避免无偿创建和处置,同时让垃圾收集器确保孤立的笔不会造成太多的内存故障。 It may, of course, not be any better in your particular case. 当然,在您的特定情况下,它可能不会更好。

Reusing the same Pen and Brush in operations that will require it many times over is going to be a lot faster than disposing of them each time with using . 在需要多次操作的操作中重复使用相同的PenBrushusing每次处理它们要快得多。

I would say for sure that it's a good idea to reuse these as much as possible (and I've seen code comparisons before, but I can't source them right now) but do remember to dispose of them when you are truly finished with them. 我肯定会说尽可能多地重用它们是个好主意(之前我已经看过代码比较,但我现在无法找到它们),但是当你真正完成它时, 记得处理掉它们。他们。

Yeah best to test like @fantius suggests, you'll probably find it doesn't really matter - although I'd be temped to keep them open as if I recall correctly they're unmanaged resources and could use up your memory. 是的,最好像@fantius一样测试,你可能会发现它并不重要 - 虽然我很想让它们保持打开状态,好像我没记错它们是非托管资源,可能会耗尽你的记忆。 If you were recreating them every time, you'd need to be especially careful of disposing them properly to avoid memory leaks. 如果您每次都在重新创建它们,则需要特别注意妥善处理它们以避免内存泄漏。

Okay this is an old question, it is probably new for some and has a simple and intuitive solution followed by a detailed explanation. 好的,这是一个老问题,对某些人来说可能是新的,并且有一个简单直观的解决方案,然后是详细的解释。

"Should I hold on to paint resources, like pens and brushes, longer than what is required to preform my painting operation", question is rephrased? “我是否应该坚持画画笔和画笔等资源,比我的绘画操作所需的时间更长”,问题会被重新定义? The answer is no, you should not in that very context; 答案是否定的,你不应该在这种情况下; but why, what does that mean? 但为什么,这意味着什么?

When you are painting to a graphics object you are using memory intensive resources for each paint object you create, be it a pen, brush, path, matrix and so on. 当您绘制到图形对象时,您正在为您创建的每个绘制对象使用内存密集型资源,无论是笔,画笔,路径,矩阵等。

Yes, do create pens, create brushes etc. for painting and do myPen.dispose() and immediately following do release all object references to the disposed object by setting that object tree to null such as (myPen = null;) this allows the garbage collector to release unmanaged memory held by these objects without having to wait for the call to object finalize(). 是的,创建笔,创建画笔等进行绘画并执行myPen.dispose()并立即执行以下操作:通过将该对象树设置为null来释放对已处置对象的所有对象引用,例如(myPen = null;)这允许垃圾收集器释放由这些对象持有的非托管内存,而不必等待对象finalize()的调用。 See: Garbage collection for more information about how garbage collection works in C#. 请参阅: 垃圾收集 ,以获取有关垃圾收集如何在C#中工作的更多信息。

Creating too many of these IDisposable class objects and not releasing these objects when finished " Using " them can have serious consequences to your program's operation such as causing possible stack and heap memory exceptions, causing increased CPU usage by having to sort through unnecessary quantities of objects potentially causing slow performance and even a runtime crash if left unchecked. 在完成“ 使用 ”它们时创建太多这些IDisposable类对象并且不释放这些对象会对程序的操作产生严重后果,例如导致可能的堆栈和堆内存异常,从而导致不必要的对象数量排序导致CPU使用量增加如果不加以检查,可能导致性能降低甚至运行时崩溃。 See about the Stack and Heap for more information. 有关更多信息,请参阅堆栈和堆

Moral of the story release resources you no longer require; 故事的道德释放您不再需要的资源; if you must retain resources, bench test the potential effects on performance when you "hold on to resources" hopefully avoiding negative consequences. 如果你必须保留资源,那么当你“保持资源”希望避免负面后果时,可以测试对绩效的潜在影响。

Rule of thumb: At the out most, ensure all resources are released upon exiting your "paint event" routine. 经验法则:最重要的是,确保在退出“绘制事件”例程后释放所有资源。 Preferably, When each of your paint event methods finish so too should any resources implicitly created by that method. 优选地,当您的每个绘制事件方法完成时,该方法隐式创建的任何资源也应如此完成。 Penalty, any object references *passed to those methods like pens and brushes etc. will be held until base object finalize is called which is longer than necessary and can be considered a memory leak in the general terms of the definition. 惩罚,任何对象引用*传递给那些方法,如笔和画笔等将被保持,直到调用基础对象finalize,这比必要的长,并且可以被认为是定义的一般术语中的内存泄漏。 *Pass too many references equals unusable memory for a longer period than what probably is expected or assumed. *传递太多引用等于不可用内存的时间比预期或假设的时间长。

Note: Cautiously pass object references like pens and brushes to methods and if doing so implement an IDisposable interface at a class level to perform your painting. 注意:小心地将对象引用(如笔和画笔)传递给方法,如果这样做,则在类级别实现IDisposable接口以执行绘制。 Your homework just got more expensive and recommend checking out the IDisposable interface . 你的作业变得更加昂贵,建议你查看IDisposable界面

Happy painting! 快乐的画!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用画笔和笔的指南 - Guidelines for Using Brushes and Pens 如何获得所有笔和画笔的阵列? - How do I get an array of all Pens and Brushes? 为什么我应该只在应用程序生命周期的早期创建MemoryCache? - Why should I only create MemoryCache early in the application lifecycle? 在WinApi中使用C#笔和画笔? - Using C# Pens and Brushes in WinApi? 每个请求创建全新的 HttpClient 是否便宜 - Is it cheap to create brand new HttpClient per request 我应该使用OwinContext的环境来保存每个请求的特定于应用程序的数据 - Should I use OwinContext's Environment to hold application specific data per request 我应该使用Lambda向Autofac注册每个请求的具体类吗? - Should I register a per request concrete class using a lambda with Autofac? 通过C#使用WebForms,如何初始化/创建在整个应用程序中使用的变量? - Using WebForms via C# how do I initialize/create variables that are used throughout my application? 如何在Windows应用程序中使线程保持活动状态C# - How to keep thread alive throughout the windows application c# 我应该对每个功能使用HttpClient还是对整个应用程序使用HttpClient? - Should I use HttpClient per function or one for whole application?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM