【问题标题】:MemoryCache UpdateCallback not workingMemoryCache UpdateCallback 不起作用
【发布时间】:2012-03-27 21:08:59
【问题描述】:

我正在尝试创建一个与第三方 API 的连接池,如果连接未使用,则在一段时间后过期。过期后需要通过第三方API断开连接。

MemoryCache (System.Runtime.Caching) 似乎可以处理这个问题。不过,UpdateCallback 的行为似乎很奇怪。

一个简单的 LINQPad 示例:

void Main()
{
    var cache = MemoryCache.Default;
    var policy = new CacheItemPolicy();
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(1);
    policy.UpdateCallback = Update;
    cache.Set("figkey", "fig", policy);

    Thread.Sleep(2000);

    object result = cache.Get("figkey");

    Console.WriteLine(result == null ? "null" : result);
}

public static void Update(CacheEntryUpdateArguments arguments)
{
    Console.WriteLine("got here");
}

如果我运行它,输出是:

fig

它确实输出“到达这里”。

如果我注释掉以policy.UpdateCallback 开头的行,则输出为:

null

我做错了什么?

如果有更好的方法来完成我的任务,我愿意接受其他建议。

【问题讨论】:

    标签: c# caching .net-4.0 memorycache


    【解决方案1】:

    我认为问题可能出在Thread.Sleep 上,因为这也会阻塞缓存,因为它们在同一个线程中运行。如果您尝试制作虚拟循环,您将触发更新处理程序:

    var i = 0;
    for (var j = 0; j < 10000000; j++)
    {
        for (var k = 0; k < 1000000; k++)
            i++;
        i--;
    }
    Console.WriteLine(i);
    

    代替睡眠。

    【讨论】:

    • 您的示例有效。我可以得到“到达这里”,然后是“null”(这是我所期望的)。这看起来很奇怪——我认为缓存过期会发生在另一个线程上。谢谢!
    【解决方案2】:

    只需在 Main 末尾添加 Console.ReadLine() 或将 Sleep 替换为 Console.ReadLine(),启动您的示例并等待大约 10 秒。您将收到预期的消息。 MemoryCache 里面的定时器有点慢。

    但无论如何,MemoryCache 中肯定存在一个错误:分配 UpdateCallback 会改变行为,但它不应该。

    如果设置了 AbsoluteExpiration 并且时间已过,则 Get 方法必须返回 null,而不依赖于 UpdateCallback 的存在。

    顺便说一句,RemovedCallback 不会改变行为。

    【讨论】:

      【解决方案3】:

      只需将睡眠时间增加到更大的时间,您就会看到回调被执行。

      通过计时器确实会在另一个线程上发生过期(如果您在回调中设置断点,您可以看到更多)。这就是睡眠或忙碌等待都有效的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-21
        • 1970-01-01
        • 1970-01-01
        • 2015-04-10
        • 2019-05-31
        相关资源
        最近更新 更多