Пул соединений: как правильно реализовать IDisposable для возврата TCP-соединения обратно в пул - PullRequest
1 голос
/ 01 апреля 2012

Я пытаюсь реализовать пул TCP-соединений и вернуть соединение обратно в пул, используя IDisposable.Мне интересно, если моя реализация верна, похоже, она работает, но я думаю, потому что базовый класс также реализует IDisposable и finalize, мой код может быть дырявым.

 public class BaseClass : IDisposable
 {
    internal bool IsDisposed { get; set; }
    private object someResource;

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

    ~BaseClass()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (someResource != null)
        {
            // some clearn up
            return;
        }

        if (disposing)
        {
            //dispose un managed resources

        }
    }
}

public class ChildClass : BaseClass
{
    // adds some functionality
}

public class MyClass : ChildClass, IDisposable
{
    MyPoolManager manager = null;

    public MyClass(MyPoolManager manager)
    {
        this.manager = manager;

    }
    public new void Dispose()
    {
        manager.ReturnPooledConnection(this);
    }
}

public class MyPoolManager
{
    private static MyPoolManager instance = new MyPoolManager();
    private static object objLock = new object();

    private static Queue<MyClass> que = null;
    private string name;

    static MyPoolManager()
    {
        que = new Queue<MyClass>();
        // enqueue some instances of MyClass here
        MyClass client = new MyClass(instance);
        que.Enqueue(client);
    }

    private MyPoolManager() { }

    public MyPoolManager(string name)
    {
        this.name = name;
    }


    public MyClass GetPooledConnection()
    {
        lock (objLock)
        {
            while (que.Count == 0)
            {
                if (!Monitor.Wait(objLock, 1000))
                    throw new TimeoutException("Connection timeout");
            }
            return que.Dequeue();
        }
    }

    public void ReturnPooledConnection(MyClass client)
    {
        lock (objLock)
        {
            que.Enqueue(client);
            Monitor.Pulse(objLock);
        }
    }
}

И вы бы использовалив вашей программе это так:

 MyPoolManager pool = new MyPoolManager();
 using (var conn = pool.GetPooledConnection())
 {
      // use the conn here
 }

 // when you reach here the conn should have returned back to the pool

1 Ответ

0 голосов
/ 01 апреля 2012

MyClass не должен определять новый Dispose (), потому что он действительно может привести к утечке ресурсов (если он не вызывает base.Dispose()).

Вместо этого вы можете использовать другой класс:

public class MyClassWrapper : IDisposable
{
    MyPoolManager manager = null;
    MyClass myClass = null;

    public MyClassWrapper(MyPoolManager manager, MyClass myClass)
    {
        this.manager = manager;
        this.myClass = myClass;

    }

    public void Dispose()
    {
        manager.ReturnPooledConnection(this.myClass);
    }

    public MyClass GetMyClass()
    {
         return this.myClass;
    }
}

Здесь отличный пост на SO о реализации IDisposable

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...