如何管理缓存的IDisposable对象?
我有一个创建成本很高的对象,它使用了一些非托管资源,必须在完成IDisposable()时显式释放这些资源。 我希望缓存这些昂贵资源的实例,以便将创建成本降到最低,但我无法知道如何处理这种处置。
如果使用这些对象的方法负责处理,那么我最终会在缓存中放置实例,然后必须重新创建这些实例,从而击败缓存点。 如果我不在使用它们的方法中处理对象,那么它们永远不会被丢弃。 我想我可以在将它们从缓存中取出时处理它们,但是最终可能会丢弃仍在使用某个方法的实例。
让它们超出范围并由垃圾收集器收集并在那时释放资源是否有效? 这感觉不对,并且反对他们被丢弃的想法...
一次性物品总是需要有一个明确的所有者负责处理它们。 但是,这并不总是创造它们的对象。 此外,所有权可以转移。
意识到这一点,解决方案变得明显。 不要处置,回收! 您不仅需要一种从缓存中获取资源的方法,还需要一种方法来返回它。 此时,缓存又是所有者,并且可以选择保留该资源以备将来使用或处置它。
public interface IDisposableItemCache<T> : IDisposable
where T:IDisposable
{
/// <summary>
/// Creates a new item, or fetches an available item from the cache.
/// </summary>
/// <remarks>
/// Ownership of the item is transfered from the cache to the client.
/// The client is responsible for either disposing it at some point,
/// or transferring ownership back to the cache with
/// <see cref="Recycle"/>.
/// </remarks>
T AcquireItem();
/// <summary>
/// Transfers ownership of the item back to the cache.
/// </summary>
void Recycle(T item);
}
编辑:我只是注意到,这个想法也存在于Spring中,它被称为对象池。 他们的BorrowObject
和ReturnObject
方法与我的例子中的方法相匹配。
(错)引用Raymond Chen:没有过期策略的每个缓存都是泄漏
因此,请设置明确的缓存过期策略,并让缓存按正常情况处理它们。 这仍然会导致应用程序关闭被处理。
如果您的非托管资源由进程拥有,您可以让进程在关闭时释放它们。
如果非托管资源不属于进程,则需要检测关闭并明确地配置缓存的元素。
如果您无法可靠地检测到进程关闭,并且托管资源非常昂贵,那么非托管资源不会将托管资源与非托管资源分开,并让缓存仅保留托管资源。
当非托管资源非常昂贵而需要缓存时,它们不属于该进程,并且无法可靠地检测到进程关闭,并且无法泄漏它们,则无法解决问题。
首先,包装本地资源的类型应该可以定型,而不只是一次性的。 更好的是,使用SafeHandle来包装原生资源。
除非有人明确说明他们已经完成了该物品并且可以处置该物品,否则我认为最好让GC处理它。 请注意,它必须是可以终结的,否则GC不会再给它第二眼。
链接地址: http://www.djcxy.com/p/9227.html