我想在我的C#应用程序中使用对象池,我知道C#中没有任何引用计数。如果同一个对象可以传递给多个线程,我怎么知道什么时候没有更多的对象引用,以便我可以将它返回到对象池?
我想过在dispose
方法中做到这一点,但是为时已晚,并且由于它已被处理,因此无法将其返回到池中。
答案 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
/ Close
或Acquire
/ Release
。
The Code Project文章 C# Object Pooling ,提供了一个很好的轻量级自定义对象池实现。
您还可以查看Connection Pooling Mechanism of ADO.NET以获得对象池示例的提示。
答案 2 :(得分:0)
我怎么知道何时没有更多对该对象的引用,以便我可以将其返回 对象池。
嗯。您实现引用计数。
它还有一个代理,它有一个Disposable方法。使用Proxy完成后,dispose实现将内部对象放入池中(外部对象tuhs非常小)。
但最后你必须知道何时发布。这称为编程。这只对具有大量初始化开销的“胖”对象有意义,然后你真的必须确保你知道什么时候用逻辑把它们放回去(即自定义计数等)。