何时将对象返回其池

时间:2012-12-30 12:38:57

标签: c# multithreading garbage-collection objectpool

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

我想过在dispose方法中做到这一点,但是为时已晚,并且由于它已被处理,因此无法将其返回到池中。

3 个答案:

答案 0 :(得分:5)

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

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

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

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

假设你有一个PooledObject类型和一个管理池的ObjectPool类型。

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

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

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

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

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

希望这会有所帮助。 奥菲尔。

答案 1 :(得分:0)

应该采用Close / Release方法。创建和处理实例的责任在于ObjectPool本身。

要从/向ObjectPool请求/释放对象,请使用Open / CloseAcquire / Release

The Code Project文章 C# Object Pooling ,提供了一个很好的轻量级自定义对象池实现。

您还可以查看Connection Pooling Mechanism of ADO.NET以获得对象池示例的提示。

答案 2 :(得分:0)

  

我怎么知道何时没有更多对该对象的引用,以便我可以将其返回   对象池。

嗯。您实现引用计数。

它还有一个代理,它有一个Disposable方法。使用Proxy完成后,dispose实现将内部对象放入池中(外部对象tuhs非常小)。

但最后你必须知道何时发布。这称为编程。这只对具有大量初始化开销的“胖”对象有意义,然后你真的必须确保你知道什么时候用逻辑把它们放回去(即自定义计数等)。