Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#GDI+;,在循环中创建LinearGradientBrush(内存泄漏)_C#_Gdi+ - Fatal编程技术网

c#GDI+;,在循环中创建LinearGradientBrush(内存泄漏)

c#GDI+;,在循环中创建LinearGradientBrush(内存泄漏),c#,gdi+,C#,Gdi+,今天我遇到了一点麻烦。我创建了一个应用程序,它使用GDI+在表单上绘图。该图形由计时器每秒触发一次。draw方法使用for循环在对象集合中迭代,如果对象处于某种状态,则绘制它们 我想用LinearGradientBrush来画它们,因为它看起来比简单的画笔好得多。请看以下内容 //minutes foreach (Led l in MinuteGrid.Leds) { LinearGradientBrush b =

今天我遇到了一点麻烦。我创建了一个应用程序,它使用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;
            }
        }
我只是想知道是否有更好的方法使用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”对象是什么?那是从哪里来的?多谢了,多谢了!你当然是对的,我有点尴尬:)拍了拍脑袋,哇!你当然是这样