我是C#的新手,正试图了解如何使用C#Lazy
。
我需要通过等待已经运行的操作的结果来处理并发请求。数据请求可能同时具有相同/不同的凭据。
对于每组唯一的凭据,最多只能有一个GetDataInternal调用正在进行中,并且该调用的结果在准备就绪时返回给所有排队的服务员
private readonly ConcurrentDictionary<Credential, Lazy<Data>> Cache
= new ConcurrentDictionary<Credential, Lazy<Data>>();
public Data GetData(Credential credential)
{
// This instance will be thrown away if a cached
// value with our "credential" key already exists.
Lazy<Data> newLazy = new Lazy<Data>(
() => GetDataInternal(credential),
LazyThreadSafetyMode.ExecutionAndPublication
);
Lazy<Data> lazy = Cache.GetOrAdd(credential, newLazy);
bool added = ReferenceEquals(newLazy, lazy); // If true, we won the race.
Data data;
try
{
// Wait for the GetDataInternal call to complete.
data = lazy.Value;
}
finally
{
// Only the thread which created the cache value
// is allowed to remove it, to prevent races.
if (added) {
Cache.TryRemove(credential, out lazy);
}
}
return data;
}
是正确的使用方式Lazy
还是我的代码不安全?
更新:
开始使用MemoryCache
代替它是个好主意ConcurrentDictionary
吗?如果是,则如何创建键值,因为它是string
内部的MemoryCache.Default.AddOrGetExisting()
这是对的。这是一个标准模式(除去模式除外),它是一个非常好的缓存,因为它可以防止缓存标记。
我不确定您要在计算完成后从缓存中删除,因为计算将一遍又一遍地重做。如果不需要删除,则可以通过基本上删除后半部分来简化代码。
请注意,Lazy
在发生异常的情况下会出现问题:会存储异常,并且永远不会重新执行工厂。该问题永远存在(直到有人重启应用程序)。在我看来,这Lazy
在大多数情况下完全不适用于生产。
这意味着诸如网络问题之类的暂时性错误可能会导致该应用永久无法使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句