3

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

本来想在dispose方法里做的,但是已经晚了,而且已经被处理掉了,无法返回池中。

4

3 回答 3

6

在 .Net 中实现对象池可以使用终结器来完成。

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

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

该技术不是在您的 Dispose 中执行任何破坏性方法(我将在接下来得到这个)并完成方法。

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

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

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

确保在 ObjectPool - GC.ReRegisterForFinalize 方法的 ReturnToPool 方法中重新注册 PooledObject 以完成最终确定。

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

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

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

于 2012-12-30T16:51:39.510 回答
0

它应该在Close/Release方法中。创建和处置实例的责任在于 ObjectPool 本身。

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

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

您还可以查看ADO.NET 的连接池机制以获取对象池示例的提示。

于 2012-12-30T12:44:45.497 回答
0

我怎么知道什么时候不再有对该对象的引用,以便我可以将它返回到对象池。

嗯。您实现引用计数。

同样有效的是它周围的代理,它有一个 Disposable 方法。完成代理后,dispose 实现将内部对象放入池中(外部对象 tuhs 非常小)。

但最后你必须知道何时释放。这称为编程。这仅对具有显着初始化开销的“胖”对象有意义,然后您必须确保您确切知道何时通过逻辑(即自定义计数等)将它们放回原处。

于 2012-12-30T12:52:04.287 回答