如何缓存IDisposable对象

Mat*_*ero 3 .net c# memory caching

假设我有这个课程:

public class StreamEntity : IPersistableEntity, IDisposable
{
     public Stream Stream { get; set; }

     public void Dispose()
     {
           if(Stream != null) Stream.Dispose();
     }
}
Run Code Online (Sandbox Code Playgroud)

现在假设我想将这个类的实例存储在某种缓存中,比如MemoryCache.

在将实体存储在缓存中之后,我继续进行操作.

一段时间后,消费者试图检索同一个实体,所以我从缓存中获取它,但是有一点问题......对象被丢弃了,所以我无法读取它的Stream属性(还记得我们在缓存之后处理它吗?)

现在,解决这个问题的一种方法是永远不要处理缓存的实体.这似乎是合乎逻辑的,因为它们应该在内存中保持活着,但在到期后会发生什么?

具体来说,当MemoryCache自动删除已过期的对象时,它会将其丢弃吗?

根据Will MemoryCache在被驱逐时处理IDisposable项目?,MemoryCache 不会处置其缓存的项目.

知道了这一点,如何缓存一次性物体?如果我无法控制他们的驱逐,我应该何时处置这些实体?

Sco*_*ain 8

你是正确的,MemoryCache不会打电话Dispose,但你可以告诉它在驱逐一个项目时调用Dispose.

static void Main(string[] args)
{
    var policy = new CacheItemPolicy
    {
        RemovedCallback = RemovedCallback,
        SlidingExpiration = TimeSpan.FromMinutes(5)
    };
    Stream myStream = GetMyStream();
    MemoryCache.Default.Add("myStream", myStream, policy);
}

private static void RemovedCallback(CacheEntryRemovedArguments arg)
{
    if (arg.RemovedReason != CacheEntryRemovedReason.Removed)
    {
        var item = arg.CacheItem.Value as IDisposable;
        if(item != null)
            item.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的例子创建了一个Stream对象,如果它在5分钟内未被使用,它将Dispose()调用它.如果由于Remove(删除项目的Set(呼叫或者覆盖该项目的呼叫而删除了该流,则它将不会对其进行Dispose()调用.

  • 我坚持缓存内容而不是流的想法,但更常用的是非常有用的+1. (2认同)