c#GDI+;,在循环中创建LinearGradientBrush(内存泄漏)
今天我遇到了一点麻烦。我创建了一个应用程序,它使用GDI+在表单上绘图。该图形由计时器每秒触发一次。draw方法使用for循环在对象集合中迭代,如果对象处于某种状态,则绘制它们 我想用LinearGradientBrush来画它们,因为它看起来比简单的画笔好得多。请看以下内容c#GDI+;,在循环中创建LinearGradientBrush(内存泄漏),c#,gdi+,C#,Gdi+,今天我遇到了一点麻烦。我创建了一个应用程序,它使用GDI+在表单上绘图。该图形由计时器每秒触发一次。draw方法使用for循环在对象集合中迭代,如果对象处于某种状态,则绘制它们 我想用LinearGradientBrush来画它们,因为它看起来比简单的画笔好得多。请看以下内容 //minutes foreach (Led l in MinuteGrid.Leds) { LinearGradientBrush b =
//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;
}
}
我只是想知道是否有更好的方法使用LinearGradientBrush?还是有更好的解决方案
非常感谢为每个Led添加渐变刷。 如果无法将其添加到该类中,则可以使用字典来存储画笔,以便轻松访问它们。 这样,每个Led只需要一个画笔,而不是每个循环迭代一个
(另外,在您的示例代码中,如果!l.IsLit!创建画笔没有意义)为每个Led添加渐变画笔。 如果无法将其添加到该类中,则可以使用字典来存储画笔,以便轻松访问它们。 这样,每个Led只需要一个画笔,而不是每个循环迭代一个 (另外,在您的示例代码中,如果!l.IsLit!创建画笔是没有意义的)我建议使用“using”语句:
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最终将收集此内存,因此无需担心。我建议使用“using”语句:
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最终将收集此内存,因此无需担心。
Dispose
与释放托管内存无关。这完全由GC处理,它“在需要时”运行。但是,由于刷子很可能有一个手柄,因此应将其弃置。我建议您在中使用
块而不是手动调用Dispose
,因为这将确保即使在出现异常时也会调用Dispose
。Dispose
与释放托管内存无关。这完全由GC处理,它“在需要时”运行。但是,由于刷子很可能有一个手柄,因此应将其弃置。我建议您在中使用
块而不是手动调用Dispose
,因为这将确保即使在出现异常的情况下也会调用Dispose
。如果排列数量有限,您可以只预先创建一次所有画笔:
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
}
List createdBrushes=newlist();
foreach(分钟网格中的Led l.Led)
{
LinearGradientBrush b=null;
b=FindOrCreateBrushBasedOnLed(l,createdBrushes);
//如果尚未创建,则创建笔刷并将其添加到列表中
作画
}
foreach(CreatedBrush中的LinearGradientBrush b)
{
清洁刷
}
其他答案是正确的,即只要不损害任何东西,.NET可能会允许托管内存使用膨胀。但如果有许多Led对象需要循环,这将有助于减少大量创建/删除操作。如果排列数量有限,您可以只预先创建一次所有画笔:
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
}
List createdBrushes=newlist();
foreach(分钟网格中的Led l.Led)
{
LinearGradientBrush b=null;
b=FindOrCreateBrushBasedOnLed(l,createdBrushes);
//如果尚未创建,则创建笔刷并将其添加到列表中
作画
}
foreach(CreatedBrush中的LinearGradientBrush b)
{
清洁刷
}
其他答案是正确的,即只要不损害任何东西,.NET可能会允许托管内存使用膨胀。但若有许多Led对象需要循环,这将有助于减少大量创建/删除操作。Clyde,非常感谢,但我建议您参考mt原始帖子。1.我无法在循环外部创建笔刷,因为创建笔刷所需的参数(led矩形)仅在循环内部已知。2.代码中的“FindOrCreateBrushBasedOnLed”对象是什么?那是从哪里来的?非常感谢,非常感谢,但我建议你们去mt的原始帖子。1.我无法在循环外部创建笔刷,因为创建笔刷所需的参数(led矩形)仅在循环内部已知。2.代码中的“FindOrCreateBrushBasedOnLed”对象是什么?那是从哪里来的?多谢了,多谢了!你当然是对的,我有点尴尬:)拍了拍脑袋,哇!你当然是这样