標準の接続プーリング モデルはありますか
ADO.NET 以外はありません。しかし、ADO.NET モデルは素晴らしくシンプルです。プールから接続を取得するオブジェクトを構築するか、新しく作成すると、クローズ/破棄/ファイナライズ時にプールに返されます。
これからすぐに実装パターンを決定できます。
- クライアント型は実際の型へのプロキシであり、作成からクローズ/… までの有効期間があります。これは、実際のオブジェクトへのプロキシです。実際の接続に転送するメソッドとプロパティを提供します。
- 実際の接続は、プールによって作成された存続期間の長いインスタンスであり、プロキシの下で提供され、プロキシの最後に返されます。
実装には選択肢があります。オブジェクトが配布された場合、プールは参照も保持する必要がありますか? その場合、プールはどのオブジェクトがアクティブで、どのオブジェクトがプールされているかを追跡する必要があります。それ以外の場合は、使用可能なオブジェクトの単純なコレクションを使用できます。
何かのようなもの:
internal class MyObjectImpl {
// The real object that holds the resource
}
internal static class MyObjectPool {
private static object syncRoot = new object();
private static Queue<MyObjectImpl> pool = new Queue<MyObject>();
private static int totalObjects = 0;
private readonly int maxObjects = 10;
internal MyObjectImplGet() {
lock (syncRoot) {
if (pool.Count > 0) {
return pool.Dequeue();
}
if (totalObjects >= maxObjects) {
throw new PoolException("No objects available");
}
var o = new MyObjectImpl();
totalObjects++;
return o;
}
}
internal void Return(MyObjectImpl obj) {
lock (syncRoot) {
pool.Enqueue(obj);
}
}
}
public class MyObject : IDisposable {
private MyObjectImpl impl;
public MyObject() {
impl = MyObjectPool.Get();
}
public void Close() {
Dispose();
}
public void Dispose() {
MyIObjectPool.Return(impl);
// Prevent continuing use, as the implementation object instance
// could now be given out.
impl = null;
}
// Forward API to implement
}
MyObject
これは、破壊された場合には対応していません。たとえば、割り当てられた への弱い参照のコレクションを保持しMyObject
、プールが空の場合は破棄されたインスタンスをチェックします。これは、クライアントがインスタンスを閉じたり破棄したり、MyObjectImpl
1にファイナライザーを実装したりすることに依存できない場合にも必要です(そして、これをデバッグ ビルドのエラーとして報告します)。
1 MyObject がファイナライズされるまでに MyObjectImpl インスタンスがすでにファイナライズされている可能性があるため、これは MyObject では実行できません。