今天我遇到了一些困境。我创建了一个使用GDI +在表单上绘制的应用程序。绘图由计时器每秒触发。 draw方法使用for循环遍历对象集合,如果它们处于某种状态,则绘制它们。
我想使用LinearGradientBrush绘制它们只是因为它看起来比简单的刷子好得多。看看下面的
//minutes
foreach (Led l in MinuteGrid.Leds)
{
LinearGradientBrush b = new LinearGradientBrush
(l.LedRectangle, Color.GreenYellow, Color.Green, 110);
if (l.IsLit)
g.FillRectangle(b, l.LedRectangle);
b.Dispose();
}
我正在为循环的每次迭代创建一个新的LinearGradientBrush(这让我困扰),但那是因为我必须这样做。我无法在循环外创建一个,因为它的构造函数集要求我设置只在循环中知道的参数。
我发现在LinearGradientBrush对象上使用dispose方法并不是那么可靠。如果我运行我的应用程序并在任务管理器中查看它,它的喷出内存。当我然后添加b = null行似乎有很大帮助,如下
foreach (Led l in MinuteGrid.Leds)
{
LinearGradientBrush b = new LinearGradientBrush
(l.LedRectangle, Color.GreenYellow, Color.Green, 110);
if (l.IsLit)
g.FillRectangle(b, l.LedRectangle);
if (b != null)
{
b.Dispose();
b = null;
}
}
我只是想知道是否有更好的方法来使用LinearGradientBrushes?或者有更好的解决方案可供使用吗?
非常感谢
答案 0 :(得分:6)
我建议使用“使用”声明:
foreach (Led l in MinuteGrid.Leds)
{
if (l.IsLit)
{
using(LinearGradientBrush b = new LinearGradientBrush(l.LedRectangle, Color.GreenYellow, Color.Green, 110))
{
g.FillRectangle(b, l.LedRectangle);
}
}
}
但是,请记住,Dispose()不会释放(托管)内存。它只是释放非托管资源(这很重要,可能包括非托管内存)。 GC运行之前内存不会释放,这可能不会在循环过程中发生。
但是,如果内存压力过高,垃圾收集器应该在你的循环中运行,你会看到它下降。这就是.NET的设计方式 - 只需接受它,不用担心。 GC最终会收集这些内存,所以不用担心。
答案 1 :(得分:0)
为每个Led添加渐变画笔。 如果你不能将它添加到该类,那么你可以使用Dictionary< Led,GradientBrush>存储画笔以便于访问它们。 这样你每个Led只需要一个刷子而不是每个循环迭代一个,
(另外,在你的示例代码中,如果没有创建画笔的点!l.IsLit)
答案 2 :(得分:0)
Dispose
与释放托管内存无关。这完全由GC处理,GC在“需要时”运行。但是,由于刷子很可能握住手柄,因此您应该将其丢弃。我建议您在using
块中执行此操作,而不是手动调用Dispose
,因为即使存在异常,也会确保调用Dispose
。
答案 3 :(得分:0)
如果排列数量有限,您可能只需预先创建一次所有画笔:
LinearGradientBrush rectGreenBrush = new LinearGradientBrush(l.LedRect........);
LinearGradientBrush rectRedBrush = new LinearGradientBrush(l.LedRect........);
foreach (Led l in MinuteGrid.Leds)
{
LinearGradientBrush b = null;
if (xxx)
b = rectGreenBrush;
else if (yyyy)
b = rectRedBrush;
else.....
do painting
}
cleanup brushes
第二个选项类似,但要根据需要创建画笔;
List<LinearGradientBrush> createdBrushes = new List<LinearGradientBrush>();
foreach (Led l in MinuteGrid.Leds)
{
LinearGradientBrush b = null;
b = FindOrCreateBrushBasedOnLed(l, createdBrushes);
// if not already created, creates the brush and adds it to the list
do painting
}
foreach (LinearGradientBrush b in createdBrushes)
{
cleanup brushes
}
其他答案是正确的,只要不损害任何内容,.NET就可以允许托管内存使用。但是,如果有许多Led对象要循环,这应该有助于减少很多创建/删除。