3

C# アプリケーションでオブジェクト プールを使用したいのですが、C# には参照カウントがないことがわかっています。同じオブジェクトを複数のスレッドに渡すことができる場合、そのオブジェクトへの参照がなくなったことをどのように知ることができ、それをオブジェクト プールに戻すことができますか?

メソッドでやろうと思ったのdisposeですが、それでは遅すぎて、破棄されてプールに戻せません。

4

3 に答える 3

6

.Net でのオブジェクト プールの実装は、ファイナライザーを使用して行うことができます。

実際、.Net に実装されているほとんどのプールもこれを行っています (たとえば、DB 接続プール)。

ファイナライザーを使用すると、GC がオブジェクトへの可能なルートがないと判断した後にファイナライザーが呼び出されるため、オブジェクトが参照されなくなったことを知ることができます。

手法は、Dispose (次はこれを取得します) および finalize メソッドで破壊的なメソッドを実行しないことです。

PooledObject タイプと、プールを管理する ObjectPool タイプがあるとします。

ObjectPool に、オブジェクトを取得して他の呼び出し元が使用できるようにする ReturnToPool(PooledObject obj) という内部メソッドを追加します。

PooledObject タイプでは、ReleaseResources という内部メソッドを追加する必要があります。これは、プール全体をメモリから削除する必要がある場合にのみ ObjectPool によって呼び出されます。このメソッドでは、破棄ロジックを実装します (ハンドルを閉じ、管理されていないメモリを解放します)。など)。PooledObject の Dispose および Finalize メソッドでは、ObjectPool (静的、またはプールされたオブジェクトに内部的に格納されている) の ReturnToPool メソッドを呼び出す必要があります。これは復活と呼ばれます。ファイナライザーで ReturnToPool メソッドを呼び出すと、実際にはオブジェクトが復活し、再び使用できるようになります。

ObjectPool - GC.ReRegisterForFinalize メソッドの ReturnToPool メソッドでファイナライズのために PooledObject を再登録していることを確認してください。

もちろん、これらのタイプは両方とも同じアセンブリにある必要があります。(相互に内部メソッドを呼び出せるようにするため)

ただし、いずれかの方法で Dispose パターンを実装する必要があります。オブジェクトがもう使用されていないとき (たとえば Using スコープを離れた後) に時間を節約し、オブジェクトをプールに返します。

お役に立てれば。オフィール。

于 2012-12-30T16:51:39.510 に答える
0

Close/Releaseメソッドにある必要があります。インスタンスの作成と破棄の責任は、ObjectPool 自体にあります。

ObjectPool との間でオブジェクトを要求または解放するには、Open/CloseまたはAcquire/を使用しますRelease

A The Code Project の記事C# Object Poolingでは、優れた軽量のカスタム オブジェクト プールの実装が紹介されています。

オブジェクト プーリングの例のヒントを得るために、ADO.NET の接続プーリング メカニズムを参照することもできます。

于 2012-12-30T12:44:45.497 に答える
0

オブジェクトへの参照がなくなったことをどのように知ることができるので、オブジェクト プールに戻すことができますか。

うーん。参照カウントを実装します。

また、Disposable メソッドを持つプロキシも機能します。Proxy の処理が完了すると、dispose の実装によって内側のオブジェクトがプールに入れられます (外側のオブジェクトは非常に小さいです)。

しかし、最終的にはいつリリースするかを知る必要があります。これをプログラミングと呼びます。これは、かなりの初期化オーバーヘッドを伴う「太った」オブジェクトに対してのみ意味があります。その場合、ロジック (つまり、カスタム カウントなど) によってオブジェクトを元に戻すタイミングを正確に把握する必要があります。

于 2012-12-30T12:52:04.287 に答える