【问题标题】:How to use MemoryCache insted of Timer to trigger a method?如何使用 Timer 的 MemoryCache 来触发方法?
【发布时间】:2015-12-15 09:25:51
【问题描述】:

以下方法通过等待已经运行的操作的结果来处理并发请求。

数据请求可能同时带有相同/不同的凭据。对于每组唯一的凭据,最多可以有一个 GetCurrentInternal 调用正在进行中,该调用的结果会在准备好时返回给所有排队的服务员。

private readonly ConcurrentDictionary<Credentials, Lazy<Data>> _dataToCredentialMap =
        new ConcurrentDictionary<Credentials, Lazy<Data>>();

public virtual Data GetCurrent(Credentials credentials)
{
    if (credentials == null) { return GetCurrentInternal(null); }

    // It will only allow a single call to GetCurrentInternal, even if multiple threads query its Value property simultaneously.
    var lazyData = new Lazy<Data>(() => GetCurrentInternal(credentials));

    var data = _dataToCredentialMap.GetOrAdd(credentials, lazyData);
    return data.Value;
}

我在构造函数的这个类中添加了timer。这是一种基于时间的失效策略,缓存条目在经过明确定义的一段时间后自动失效。

_dataUpdateTimer = new Timer(UpdateData, null, TimeSpan.Zero, _dataUpdateInterval); // 1 min

更新数据的方法如下:

private void UpdateData(object notUsed)
{
    try
    {
        foreach (var credential in _dataToCredentialMap.Keys)
        {
            var data = new Lazy<Data>(() => GetCurrent(credential));
            _dataToCredentialMap.AddOrUpdate(credential, data, (k, v) => data);
        }
     }
     catch (Exception ex)
     {
          _logger.WarnException(ex, "Failed to update agent metadata");
     }
}

我想使用我的ConcurrentDictionaryTimer 的.Net MemoryCache 类来更新我的Credential and Data,我认为它会更有效。

我知道如何使用MemoryCache 而不是ConcurrentDictionary,但是如何在没有Timer 的构造函数中每分钟调用UpdateData

你能帮我看看怎么做吗?

【问题讨论】:

  • 只需使用允许您传递 DateTimeOffset 的 Set/AddOrGetExisting() 重载。 DTO 指定项目何时被驱逐,与您的计时器相同。
  • MemoryCache 不支持确保每个键只创建一个值。你现有的方法很好。
  • @usr 所以我可以依靠ConcurrentDictionary 只有一个线程可以GetOrAdd 一些键/值,但是如果我将此行更改为 MemoryCache.Default.AddOrGetExisting(...) 它会是一个错误?
  • @usr 即使之前的调用 var lazyData = new Lazy&lt;Data&gt;(() =&gt; GetCurrentInternal(credentials)); 是线程安全的?
  • 实际上,我不确定 AddOrGetExisting 能保证什么。可能您需要查看文档,因为我不确定。

标签: c# multithreading memorycache


【解决方案1】:

您可以在没有计时器的情况下使用 MemoryCache 执行此操作。只需将 CacheItemPolicy 设置为 AbsoluteExpiration:

MemoryCache memCache = MemoryCache.Default;
memCache.Add(<mykey>, <myvalue>,
          new CacheItemPolicy()
          {
            AbsoluteExpiration = DateTimeOffset.Now.Add(TimeSpan.FromMinutes(_expireminutes)),
            SlidingExpiration = new TimeSpan(0, 0, 0)
          }
          );

【讨论】:

  • 我的_dataUpdateTimer 每分钟拨打UpdateData。在UpdateData 里面我更新了我的字典。您如何编写代码可以仅使用 MemoryCache 做同样的事情?
  • 你可以对缓存项的驱逐事件做出反应
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-23
  • 2015-07-07
  • 1970-01-01
相关资源
最近更新 更多