何时将对象返回其池

ger*_*tla 3 c# multithreading garbage-collection objectpool

我想在我的C#应用​​程序中使用一个对象池,我知道C#中没有任何引用计数.如果同一个对象可以传递给多个线程,我怎么知道什么时候没有更多对该对象的引用,以便我可以将它返回到对象池?

我想在dispose方法中做到这一点,但是为时已晚,并且由于它被丢弃,所以它无法返回到池中.

小智 6

在.Net中实现对象池可以使用Finalizer完成.

实际上,.Net中实现的大多数池也是这样做的(例如 - 数据库连接池).

使用终结器可以让您知道该对象不再被引用,因为在GC确定没有可能到该对象的路径之后调用终结器.

该技术不是在你的Dispose中做任何破坏性的方法(我接下来会得到这个)并最终确定方法.

假设您有一个PooledObject类型和一个管理池的ObjectPool类型.

在ObjectPool中,添加一个名为ReturnToPool(PooledObject obj)的内部方法,该方法将获取该对象并使其可供其他调用者使用.

在PooledObject类型中,您应该添加一个名为ReleaseResources的内部方法 - 只有在从内存中删除整个池时,ObjectPool才会调用该方法 - 在此方法中,您将实现您的dispose逻辑(关闭句柄,释放未管理的内存)等等.).在PooledObject Dispose和Finalize方法中,您应该调用ObjectPool中的ReturnToPool方法(静态或内部存储在池化对象中) - 这称为 - 复活.在终结器中调用ReturnToPool方法时,实际上是复活对象并使其再次可用.

确保在ObjectPool中的ReturnToPool方法中重新注册PooledObject以进行最终化 - GC.ReRegisterForFinalize方法.

当然,这两种类型都应该在同一个程序集中.(以确保他们可以互相调用内部方法)

但是,您应该以任一方式实现Dispose模式.它将节省不再使用对象的时间(例如在离开使用范围之后)并将对象返回到池中.

希望这可以帮助.奥菲尔.

  • 这个答案非常正确但是**非常非常小心**如果使用终结器实现池化对象.犯错是非常非常容易的.请记住,在终结器中,*您通常的假设都不是真的*.该对象可能尚未完全构建.当前线程不是您的任何线程.该对象被GC视为死亡.对象所指的任何东西也可能已经死亡.等等.如果你走这条路的话,要非常谨慎*.我建议人们明确地将对象返回池中,而不是追求最终策略. (5认同)