【发布时间】:2020-11-07 12:20:39
【问题描述】:
我正在为 memoryCache 寻找线程安全的“GetAsync”版本。
我知道有“GetOrCreateAsync”,但在提交一些数据之前,我需要检查它是否存在于缓存中。
我一直在谷歌上搜索,但我没有找到一个 ThreadSafe “GetAsync” 方法,即使在有赛车条件的情况下我也可以安全使用。
是否有“GetOrCreateAsync”版本但只是 GET?
有什么建议吗?
更新
最后我使用了 GetOrAddAsync,如下所示
private readonly SemaphoreSlim locker = new SemaphoreSlim(1, 1);
public async Task<T> GetOrAddAsync<T>(object key, Func<ICacheEntry, Task<T>> create)
{
await locker.WaitAsync();
try
{
return await cache.GetOrCreateAsync(key, create);
}
finally
{
locker.Release();
}
}
我是这样测试的
var tasks = new List<Task>();
var counter = 0;
for (int i = 0; i < 10; i++)
{
var index = i;
tasks.Add(Task.Run(async () =>
{
var x = await cache.GetOrAddAsync("test", entry => Task.FromResult(Interlocked.Increment(ref counter)));
output.WriteLine($"Interaction {index} got {x}");
}));
}
await Task.WhenAll(tasks);
output.WriteLine("Counter {0}", counter);
Assert.True(counter == 1);
}
这个测试有什么好处并证明可以处理竞争条件吗?
【问题讨论】:
-
内存缓存没有理由拥有
GetAsync方法,因为在get 上没有什么可以做的异步操作。它是一个内存缓存,因此没有 IO 可以从外部源(例如数据库或文件)获取缓存值。 -
@Evk 感谢您的解释,我想我正在掌握所有这些缓存内容及其工作原理。如果您喜欢 Get 找不到该项目,因为 add 仍在执行此操作,是否存在竞争条件?我有一个只应该执行一次的方法,我添加了一个“键”来缓存,例如“ref123”,但如果再次调用,我只需要搜索“ref123”,如果找到不执行方法。希望是有道理的
-
但这不正是
GetOrCreate(或GetOrCreateAsync,如果获取值的方法是异步的)所做的吗? -
让我们假设我只想缓存一个字符串值,例如“ref123”,过期时间为 3 分钟 GetOrCreateAsync 等。将始终返回我一个值,因为如果不存在它会创建一个值,我需要什么在我的场景中简单来说,如果一个值不存在 GetAsync 将返回 null
-
@aepot 嗨,你有使用它的样本吗
标签: c# caching xamarin.forms memorycache