質問

ImageList から画像を取得するときに OutOfMemoryException が発生します。問題に対する適切な解決策が見つかりません。

カスタム ListView コントロールを持っています。これには、ListViewItems を描画するためのイベントがアタッチされています。次に、項目を描画するように設計された静的メソッドを呼び出します。

約 300 項目の ListView の場合、ListView がスクロールされるたびにメモリが約 100Mb 増加します。問題のあるコードは次のように追跡されています。

Image image = item.ImageList.Images[item.ImageKey];
if (image != null)
{
    Size imageOffset = new Size((bounds.Width - image.Width) / 2, 2); 
    Point imagePosition = bounds.Location + imageOffset;
    graphics.DrawImageUnscaled(image, imagePosition);
}

(WinXP では確かに) ガベージ コレクションが正しく動作せず、メモリのスパイラルを引き起こしているようです。この問題を解決するために、コード ブロックの直後に image.Dispose() を追加しようとしましたが、効果はありません。

これまでのところ私が見つけることができた唯一の解決策は、静的メソッドの最後で GC.Collect() を呼び出すことです。ただし、これの問題は、ListView 自体の再描画が遅くなり、再描画中に画面上にアーティファクトが表示されることです。

他にこれを経験した人はいますか?それとも回避策を知っていますか?

役に立ちましたか?

解決

処分していますか graphics?また、あなたが述べたように画像を破棄する場合は、それが ImageList から削除されていることを確認する必要があります。そうしないと、さらに問題が発生します。画像の形式は何ですか?

一般に、画像が関係するときにメモリ不足の問題が発生する場合、問題は、一部のメソッドが一部の画像形式を好まないか、または 9/10 の場合、グラフィック オブジェクトの 1 つのライフサイクルを誤解しているかのどちらかです。

  • すべてをチェックしてください Graphics 使用してそれらを入れます using ブロック。
  • あなたの Image ライフサイクルに注意し、コピー、破棄、基になるストリームの終了などに注意してください。
  • メモリ マネージャー (VS2008 にはメモリ マネージャーが組み込まれています) をロードし、何がうまくクリーンアップされていないのかを確認します。

編集:

これが私が見つけることができる最良のオプションです、使用してください ImageList.Draw(graphics, x, y, width, height, index). 。これにより、イメージのコピーを作成する代わりに内部ハンドルが使用されます。

他のヒント

私は自分のアプリケーションでこの問題を解決するために管理している。

ジェイソンはあなたがブロック、またはそれに相当する「を使用して」使用を確認する必要があり、答えを持っています。

私はVBを使用して、同等の私はBitMap.Disposeを呼び出し、「最後に」の部分でビットマップ=何も設定していない、新しいビットマップを作成した。最後たび...キャッチ...してみ使用することでした。

これは、私がGoogleにこれをしようとして過ごしてきた時間から判断すると、実際に共通の問題であると思われます。以下のコードは、Googleには難しいことのようです別の問題、サムネイルに縮小されたときに任意の画像は、その縦横比を保持することができます!

コード:

Private Function AspectedImage(ByVal ImagePath As String, ByVal SizeWanted As Integer) As Image

    Dim myBitmap, WhiteSpace As System.Drawing.Bitmap
    Dim myGraphics As Graphics
    Dim myDestination As Rectangle
    Dim MaxDimension As Integer
    Dim ReductionRatio As Double

    Try

        'create an instance of bitmap based on a file
        myBitmap = New System.Drawing.Bitmap(ImagePath)



        'create a new square blank bitmap the right size
        If myBitmap.Height >= myBitmap.Width Then MaxDimension = myBitmap.Height Else MaxDimension = myBitmap.Width
        ReductionRatio = SizeWanted / MaxDimension
        WhiteSpace = New System.Drawing.Bitmap(SizeWanted, SizeWanted)

        'get the drawing surface of the new blank bitmap
        myGraphics = Graphics.FromImage(WhiteSpace)

        'find out if the photo is landscape or portrait
        Dim WhiteGap As Double

        If myBitmap.Height > myBitmap.Width Then 'portrait
            WhiteGap = ((myBitmap.Width - myBitmap.Height) / 2) * -1
            myDestination = New Rectangle(x:=CInt(WhiteGap * ReductionRatio), y:=0, Width:=Int(myBitmap.Width * ReductionRatio), Height:=Int(myBitmap.Height * ReductionRatio))
        Else 'landscape
            WhiteGap = ((myBitmap.Width - myBitmap.Height) / 2)
            'create a destination rectangle
            myDestination = New Rectangle(x:=0, y:=CInt(WhiteGap * ReductionRatio), Width:=Int(myBitmap.Width * ReductionRatio), Height:=Int(myBitmap.Height * ReductionRatio))
        End If

        'draw the image on the white square
        myGraphics.DrawImage(image:=myBitmap, rect:=myDestination)
        AspectedImage = WhiteSpace

    Catch ex As Exception
        myBitmap = New System.Drawing.Bitmap("")
        AspectedImage = New System.Drawing.Bitmap(4, 4)
        ImageBufferExceeded = True
        MsgBox("Image Buffer exceeded, too many images in memory. If the one(s) you want can't be seen, please restart the application and navigate straight to your images")
    Finally
        myBitmap.Dispose()
        myBitmap = Nothing
        WhiteSpace = Nothing
    End Try

End Function
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top