Pur*_*ome 5 .net c# asynchronous concurrentdictionary
有各种 帖子/答案表示,如果键尚不存在,则ConcurrentDictionary GetOrAdd当使用委托计算要插入字典中的值时,.NET/.NET Core 的方法不是线程安全的。Func
我相信,当使用 aConcurrentDictionary的方法的工厂方法时GetOrAdd,如果“同时”发生多个请求,则可以“同时/快速连续地”多次调用它。这可能会造成浪费,尤其是当呼叫“昂贵”时。(@panagiotis-kanavos 比我解释得更好)。有了这个假设,我正在努力理解我制作的一些示例代码似乎是如何工作的。
我已经在 .NET Fiddle 上创建了一个工作示例,但我一直试图理解它是如何工作的。
普通的推荐我读过的建议/想法是Lazy<Task<T>>在ConcurrentDictionary. 这个想法是阻止Lazy其他调用执行底层方法。
完成繁重工作的代码的主要部分是这样的:
public static async Task<DateTime> GetDateFromCache()
{
var result = await _cache.GetOrAdd("someDateTime", new Lazy<Task<DateTime>>(async () =>
{
// NOTE: i've made this method take 2 seconds to run, each time it's called.
var someData = await GetDataFromSomeExternalDependency();
return DateTime.UtcNow;
})).Value;
return result;
}
Run Code Online (Sandbox Code Playgroud)
我是这样读的:
someDateTime字典中是否存在 key。Lazy<Task<DateTime>>(基本上是即时的)Lazy实例。(到目前为止,尚未调用实际的“昂贵”操作。)Value,这是一个Task<DateTime>。await这个任务..最终完成了“昂贵”的调用。它等待 2 秒......然后返回结果(某个时间点)。现在这就是我错的地方。因为我假设(上面)键/值中的值是Lazy<Task<DateTime>>...await每次都会调用。如果await一次调用一个(因为它Lazy可以保护其他调用者同时不被所有调用),那么我会认为DateTime每个独立调用的结果都会不同。
那么有人可以解释一下我的想法哪里错了吗?
(请参考.NET Fiddler中完整的运行代码)。
因为我假设(上面)键/值中的值是
Lazy<Task<DateTime>>
是的,确实如此。
每次都会调用 wait 。如果一次调用一个等待(因为惰性保护其他调用者不会同时调用所有调用),那么我会认为每次独立调用的结果都会是不同的日期时间。
wait 不是一个调用,它更像是“当结果可用时继续执行”。访问Lazy.Value将创建任务,这将启动对GetDataFromSomeExternalDependency最终返回日期时间的调用。您可以根据需要多次等待该任务并获得相同的结果。