问题
The following method handle concurrent request by waiting the result of an already running operation.
Requests for data may come in simultaneously with same/different credentials. For each unique set of credentials there can be at most one GetCurrentInternal
call in progress, with the result from that one call returned to all queued waiters when it is ready.
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;
}
And I have added timer
inside of this class in constructor. It's time-based invalidation policy where cache entries are auto-invalidated after a certain well-defined period of time.
_dataUpdateTimer = new Timer(UpdateData, null, TimeSpan.Zero, _dataUpdateInterval); // 1 min
Method that update data looks like the following:
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");
}
}
I would like to use .Net MemoryCache
class insted of my ConcurrentDictionary
and Timer
, to update my Credential and Data
I think it will be more efficient.
I know how I can use MemoryCache
instead of ConcurrentDictionary
, but how can I call UpdateData
each minute in constructor without a Timer
?
Can you help me please how to do that?
回答1:
You can do this with MemoryCache without a Timer. Just set the CacheItemPolicy to AbsoluteExpiration:
MemoryCache memCache = MemoryCache.Default;
memCache.Add(<mykey>, <myvalue>,
new CacheItemPolicy()
{
AbsoluteExpiration = DateTimeOffset.Now.Add(TimeSpan.FromMinutes(_expireminutes)),
SlidingExpiration = new TimeSpan(0, 0, 0)
}
);
来源:https://stackoverflow.com/questions/34285365/how-to-use-memorycache-insted-of-timer-to-trigger-a-method