2012-05-13 10 views
4

私はネイティブdllのラッパーである第三者のライブラリを使用します。ライブラリにはタイプ​​,​​にはいくつかのプロパティがあり、IntPtr Data()メソッドがあります。​​IDisposableも実装されていますが、正しく実装されているかどうかはわかりません。アンマネージドリソースを使用して作業する

TCP接続から多くの​​を取得し、PictureBoxの映画として表示します。

私は 'XImage'をSystem.Drawing.Imageに変換し、PictureBoxで表示しましたが、私はAccessViolationExceptionを得ました。

Frameという​​のラッパーを作った。

public class Frame : IDisposable 
{ 
    public uint size { get; private set; } 
    private Image image; 
    public XImage XImage { get; set; } 
    public Image Image { get { return image ?? (image = GetBitmap(this.XImage)); } } 
    public DateTime Time { get; set; } 

    public Frame(XImage xImage) 
    { 
    this.XImage = xImage; 
    this.size = XImage.ImageBufferSize(); 
    GC.AddMemoryPressure(size); 
    } 


    public void Dispose() 
    { 
    Dispose(true); 
    GC.SuppressFinalize(this); 
    } 

    ~Frame() 
    { 
    Dispose(false); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
    if (disposing) 
    { 
     try 
     { 
     image.Dispose(); 
     } 
     catch { } 
     finally 
     { 
     image = null; 
     } 
     try 
     { 
     MImage.Dispose(); 
     } 
     catch { } 
     finally { XImage = null; } 
    } 
    GC.RemoveMemoryPressure(size); 
    } 
} 

と私はAccessViolationExceptionを解決Frameへの参照を扱うこともできます。 今私はビジュアルスタジオ(F5 - 起動デバッグ)からプログラムを実行すると、すべての問題はありませんが、.exeファイル(またはctrl + F5 - デバッグなしで起動)からメモリ使用量が大きくなっていますOutOfMemoryExceptionを取得するまでは大きくなります(Biuld Configuration:Release-X86)。私は何をすべきか ?

---- EDIT ----

私はGC.AddMemoryPressureGC.RemoveMemoryPressureがちょうどより頻繁に実行するためにガベージコレクションを作ることがわかったと、私の問題は、私はへのハンドルを持っている小さなオブジェクトを持っているということになりました大規模な管理されていないメモリであり、GCはこれらの小さなオブジェクトを収集していません。そう

---- EDIT ----
GC.Collectを呼び出すと、実行時に問題を解決します、私はタイマーを設定し、定期的にGC.Collectを呼ぶが、それは短い期間のためのアプリケーションのフリーズを行い、私はこのアプローチを使いたくありません。

+2

あなたはそれを解決していない、あなたはすべての例外をキャッチしてそれを隠した。後で問題を解決することは避けられません。このような問題を引き起こすライブラリを捨てなさい。 –

+0

'Dispose()'メソッドですべての例外を呑み込んでいるだけです。 XImageが実際にうまく処理できなかった可能性があります。 – angelsl

+0

@HansPassant:私は図書館が大丈夫だと思います。私はタイマーを設定し、GC.Collect()を30秒ごとに呼び出し、 'OutOfMemoryException'を解決しますが、これは良いアプローチではありません。デバッガでの実行がデバッガなしでの実行と異なる理由 – HPT

答えて

0

私は、GCには制限があり、非常に重い圧力下でもメモリの強いアプリケーションではあまりうまく機能しないことがわかりました。私は、アンマネージリソースを何もしないアプリケーション、標準の.NETコンポーネントをすべて持っています。膨大なメモリが必要なためではなく、大きなオブジェクトが比較的早く作成され、破棄され、明らかにあまり収集されないため、GBsのRAMを使用できます。アプリケーションは、コレクションが強制されるとすべて解放されるため、メモリリークはありません。 GCは、未使用のオブジェクトを、つまりOutOfMemoryExceptionの前に必ず収集できるとは限りません。それは最高の瞬間を見つけるのを待つが、それが心を構成する前にそれは遅すぎる。定期的にコレクションを強制すると、アプリケーションは問題なく実行されます。

OutOfMemoryExceptionは、実際に空きメモリが足りないことを必ずしも意味するわけではありません。また、利用可能な十分な連続したメモリチャンクがないことも意味します。これは、特にビデオや画像を扱う場合に当てはまります。 GCはメモリがまだ十分にあると思うかもしれませんが、あなたのアプリケーションのために断片化されています。 GCは断片化を考慮していると確信していますが、必ずしも正しいとは限りません。

ライブラリーに問題がない場合は、GCを時間通りに行うのに役立つように、メモリー圧力メソッド(AddMemoryPressureおよびRemoveMemoryPressure)をさらに実験することをお勧めします。GCの背後にある相当量のメモリを処理しているかもしれない管理されていないライブラリで作業するため、問題を解決する可能性があります。あるいは、GC.Collectと同じようにしてください。手作業による収集は理想的ではないかもしれませんが、正当化される場合があると私は信じています。もちろん、多くのオブジェクトを手動で収集すると、アプリケーションのパフォーマンスに影響を与える可能性があります。

EDIT

マニュアルコレクションは、パフォーマンスへの影響をあまりを紹介する場合は、あなたにもう少しコントロールを与えるGC.Collectのオーバーロードされたバージョンを使用するようにしてください。

+0

GC.AddMemoryPressureまたはGC.RemoveMemoryPressureがガベージコレクションをより頻繁に実行することを発見しました。私の問題は、大きなアンマネージドメモリのハンドルを持つ小さなオブジェクトがあり、GCがこれらの小さなオブジェクトを収集していないことです。 – HPT

+0

オブジェクトを解放できる場合は、OOMを取得しないでください。しかし、それはまだどこかで参照されている可能性があります。たとえば、ファイナライズキューです。それ以外は、ここではあまり関係ないようです。 – svick

+0

私はまったく同じだと思います。オブジェクトを保留中のオブジェクト(ファイナライズキュー内であっても)がOOMにつながるべきではありません。残念ながら、これは実際には時々起こります。 –

関連する問題