For each unique set of credentials there can be at most one GetData call in progress, with the result from that one call returned to all queued waiters when it is ready.
private readonly ConcurrentDictionary<MetadataCredentials, Lazy<AgentMetadata>> _credentialToMetadataMap =
new ConcurrentDictionary<MetadataCredentials, Lazy<AgentMetadata>>();
public virtual AgentMetadata GetCurrent(MetadataCredentials metadataCredentials)
{
var agentMetadata = new Lazy<AgentMetadata>(() => GetData(metadataCredentials));
var lazyMetadata = _credentialToMetadataMap.GetOrAdd(metadataCredentials, agentMetadata);
bool isAdded = ReferenceEquals(agentMetadata, lazyMetadata);
try
{
return lazyMetadata.Value;
}
catch (AggregateException ex)
{
throw ex.InnerException;
}
finally
{
// Only the thread which created the cache value is allowed to remove it, to prevent races.
if (isAdded)
{
_credentialToMetadataMap.TryRemove(metadataCredentials, out lazyMetadata);
}
}
}
All of my unit tests works fine when I use Lazy
. But I want to use Task
, so I change the following lines:
ConcurrentDictionary<MetadataCredentials, Task<AgentMetadata>> _credentialToMetadataMap;
var agentMetadata = new Task<AgentMetadata>(() => GetData(metadataCredentials));
try
{
lazyMetadata.Wait();
return lazyMetadata.Result;
}
It doesn't work. How to change my code to equivalent but with Task
, without async/await
?