【发布时间】: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");
}
}
我想使用我的ConcurrentDictionary 和Timer 的.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<Data>(() => GetCurrentInternal(credentials));是线程安全的? -
实际上,我不确定 AddOrGetExisting 能保证什么。可能您需要查看文档,因为我不确定。
标签: c# multithreading memorycache