2009-08-26 4 views
1

今日、私は少しのジレンマに出くわしました。私はGDI +を使ってフォーム上に描画するアプリケーションを作成しました。描画は毎秒タイマーによってトリガーされます。 drawメソッドはforループを使用してオブジェクトのコレクションを反復処理し、ある状態のものを描画します。C#GDI +、ループ内でのLinearGradientBrushの作成(メモリリーク)

は、私はそれが簡単なブラシよりもそんなに立派に見えるという理由だけで、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を作成していますが、私はする必要があるためのthats。コンストラクタセットでループ内でしか知ることのできないパラメータを設定する必要があるため、ループ外には作成できません。

私はLinearGradientBrushオブジェクトのDisposeメソッドを使用すると、すべてのこと信頼できるものではないことがわかります。私のアプリケーションを実行し、タスクマネージャでそれを見る場合、その噴出するメモリ。私はその後、

  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; 
      } 
     } 

を次のように非常に役立つように思わB =空行を追加するとLinearGradientBrushesで作業するより良い方法がある場合、私はちょうど疑問に思って?または、より良いソリューションを使用することはできますか?

多くの感謝

答えて

0

各Ledにグラデーションブラシを追加します。 あなたはそのクラスに追加することができない場合は、それらへの容易なアクセスを獲得するには、ブラシを保存するために辞書<ツェッペリン、GradientBrush >を使用することができます。 あなたはLEDのみの代わりに、ループの反復ごとにごとに1つのブラシを必要とするそのように、

は、私が使用することをお勧めします

+0

スラップヘッド、ドゥ!もちろんそれはちょっと恥ずかしいよね:) –

6

(また、あなたのコード例では、ブラシ!l.IsLit場合を作成しても意味がありません)声明 "を使用して":

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); 
     } 
    } 
} 

しかし、)(、廃棄を覚えが空きメモリを(管理)しません。これは、アンマネージリソースを解放するだけです(これは重要であり、アンマネージメモリを含む場合もあります)。メモリはGCが実行されるまで解放されません。これはループ中には発生しません。

メモリ圧力が高すぎる場合には、ガベージコレクタは、あなたのループ内で実行する必要があり、そしてあなたはそれがドロップ表示されます。これは.NETが設計された方法です。ただそれを受け入れ、心配しないでください。 GCは最終的にはこのメモリを収集するので、心配する必要はありません。

+0

ビンゴ...あなたの理論をテストするには、各実行の最後にgc.collectを呼び出して、メモリがre-claims ...キーワードかどうかを確認する必要がありますこれは "テスト"ですが、gc.collectsをプロダクションコードに残さないでください。 –

0

Disposeが管理するメモリを解放するとは何の関係もありません。これはGCによって完全に処理され、必要に応じて実行されます。しかし、ブラシはハンドルを保持する可能性が最も高いので、それを処分する必要があります。 Disposeを手動で呼び出す代わりに、usingブロックでこれを行うことをお勧めします。これにより、例外が発生してもDisposeが呼び出されるようになります。

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オブジェクトがたくさんある場合、作成/削除の多くをカットするのに役立ちます。

+0

クライド、多くのおかげさまですが、私はオリジナルの投稿を参照してください。 1.作成に必要なパラメータ(led rectangle)はループ内でしか認識されないため、ループ外にブラシを作成することはできません。 2.コード内の "FindOrCreateBrushBasedOnLed"オブジェクトとは何ですか?それはどこから来たのですか? 多くのありがとう –

関連する問題