3


1

所有しているものすべてを解放できるようにオブジェクトを破棄する必要がありますが、IDisposableを実装していないため、usingブロックでは使用できません。 ガベージコレクタに収集させるにはどうすればよいですか。

6 Answer


9


GC.Collect()でコレクションを強制することができます。 フルコレクションには時間がかかることがあるので、これを使用する際は十分に注意してください。 ベストプラクティスは、収集する最善の時期がいつになるかをGCに判断させることです。

オブジェクトにアンマネージドリソースが含まれていますが、IDisposableを実装していませんか? もしそうなら、それはバグです。

そうでなければ、それがすぐに解放されるかどうかは関係ありません、ガベージコレクタは正しいことをするべきです。


2


メモリ以外のものを「所有」している場合は、IDisposableを使用するようにオブジェクトを修正する必要があります。 それがあなたがコントロールするオブジェクトではないなら、これはあなたのベンダーがどれほどよく.Netを理解しているかの核心について話すので、これは別のベンダーを選ぶ価値がある何かです。

それだけでメモリを所有しているのであれば、多くの場合でも、あなたがしなければならないのは、オブジェクトが範囲外になることを確認することだけです。 `+ GC.Collect()+`を呼び出さないでください。これは、尋ねる必要がある場合は実行しないでください。


2


単一のオブジェクトに対してガベージコレクションを実行することはできません。 GC.Collect()を呼び出すことでガベージコレクションを要求できますが、これはクリーンアップの対象となるすべてのオブジェクトに影響します。 また、後のコレクションのパフォーマンスに悪影響を及ぼす可能性があるため、あまりお勧めできません。

また、オブジェクトに対してDisposeを呼び出しても、そのメモリはクリーンアップされません。 オブジェクトが管理されていないリソースへの参照を削除することのみを許可します。 たとえば、StreamWriterでDisposeを呼び出すと、ストリームが閉じられ、Windowsファイルハンドルが解放されます。 マネージヒープ上のオブジェクトのメモリは、その後のガベージコレクションまで回収されません。

Chris Sellも.NET Rocksでこれについて議論しました。 私はそれが彼の最初の出演中だったと思いますが、この話題は後のインタビューで再検討されたかもしれません。

Francesco Balenaによるこの記事も参考になります。

いつ、どのようにC#で破棄してファイナライズするか http://www.devx.com/dotnet/Article/33167/0/page/1


0


オブジェクトが範囲外になり、外部参照がない場合は、かなり速く収集されます(おそらく次のコレクションで)。


0


NETでのガベージコレクションは決定論的ではないため、いつ発生するかを実際に制御することはできません。 あなたは提案することができますが、それはそれが聞いてくれるという意味ではありません。

オブジェクトについて、もう少し詳しく説明します。 それに基づいていくつか提案をすることができます。 コードは常に役に立ちます。 オブジェクトによっては、Closeメソッドなどがあるかもしれません。 使用法はそれを呼び出すことです。 CloseまたはDisposeタイプのメソッドがない場合、実際には解放する必要があるリソースが含まれていると、おそらくメモリリークが発生するため、おそらくそのオブジェクトに頼らないでください。


-2


  • BEWARE:* of フラグメンテーション*多くの場合、_GC.Collect()_やいくつかの_IDisposal_は*あまり役に立ちません、特にラージオブジェクトの場合(_LOH_はオブジェクトのための*〜80kb *、*圧縮なし) *そして、多くの一般的なユースケースでは*高レベルのフラグメンテーションが発生する可能性があります)、潜在的に_数百MBの空き容量がある場合でも*メモリ不足(OOM)*の問題が発生します。 時間が経つにつれて、LOH関連オブジェクトではこのサイズ(80何かkb)ではないかもしれませんが、物事はますます大きくなります。インスタンス化/解放

*配列*はこの問題の_疑わしい_疑わしいものです(非特異的な例外やランタイムからのアサーションのために識別するのは難しいことが多く、「ラージオブジェクトヒープ断片化の高い%」のようなものは膨張するでしょう)。 *この問題を抱えているコードのために*積極的な再利用戦略を実装することです。

http://code.msdn.microsoft.com/ParExtSamples/Release/ProjectReleases.aspx?ReleaseId=2704[パラレル拡張機能beta1サンプル]の_Systems.Collections.Concurrent.ObjectPool_のクラスが役に立ちます(残念ながら単純なユビキタスはありません)。私が見たパターンは、おそらくいくつかの添付プロパティ/拡張メソッドのように、ドロップインするか、ほとんどのプロジェクトに再実装するのに十分簡単です、あなたはジェネレータFunc <>を割り当て、再利用するためにGet / Putヘルパーメソッドを使いますあなたの前のオブジェクトのもので、通常のガベージコレクションは不要です。 通常は個々の配列要素ではなく*配列*に焦点を合わせるだけで十分です。
NET 4が.ToArray(T target)を含むようにいたるところですべての.ToArray()メソッドを更新したなら、それは素晴らしいことです。

この種の問題を分析するために* SOS * / windbg (CLRv4の場合はloadby sos mscoreei)を使用する手間が省けます。 それを考えると、現在のガベージコレクションシステムは、(同じ物理メモリを再び使用する)ガベージリサイクリングに似ていますが、ObjectPoolはガベージリユースに似ています。 もし誰かが3つのRを覚えているのなら、あなたのメモリ使用量を減らすこともパフォーマンスのために良い考えです。