我有一个使用Ninject for DI的ASP.NET MVC5应用程序。我有一个消息显示在每个页面的顶部。该消息是使用异步操作从一个web服务中获取的。该消息本身很小,更新频率也不高,所以我想把它缓存在内存中。
我创建了一个简单的服务,配置为DI单人。我有一个很好的事情要做 ReaderWriterLock
但它不支持异步。所以我试着用以下方法重新创建同样的东西 SemaphoreSlim
. 这就是我的想法
public class ExampleService {
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1);
private DateTime? lastAccess = null;
private string cachedMessage = null;
public async Task<string> GetMessageAsync() {
if (lastAccess.HasValue && lastAccess.Value > DateTime.UtcNow.AddHours(-1)) {
return cachedMessage;
}
var writeable = semaphore.CurrentCount == 1;
await semaphore.WaitAsync();
try {
if (writeable) {
// Do async stuff
}
}
finally {
semaphore.Release();
}
return cachedMessage;
}
~ExampleService() {
if (semaphore != null) semaphore.Dispose();
}
}
目标是让所有的电话等到 cacheMessage
被填充,然后把它给每个人。我的解决方案的问题是,一旦写调用完成,所有等待的读实际上都卡在队列中被逐一释放,而新的读则可以完全跳过队列。
有什么更好的方法吗?
更新
基于此 岗位,很多人似乎都主张只使用 LazyCache. 制作实现。
public class ExampleService {
private readonly IAppCache cache;
public ExampleService(IAppCache cache) {
this.cache = cache;
}
private async Task<string> GetMessageFromServerAsync() {
// result = async stuff
return result;
}
public async Task<string> GetMessageAsync() {
return await cache.GetOrAddAsync("MessageKey", GetMessageFromServerAsync);
}
}
基于这个 岗位,很多人似乎都主张只使用 LazyCache. 使实施。
public class ExampleService {
private readonly IAppCache cache;
public ExampleService(IAppCache cache) {
this.cache = cache;
}
private async Task<string> GetMessageFromServerAsync() {
// result = async stuff
return result;
}
public async Task<string> GetMessageAsync() {
return await cache.GetOrAddAsync("MessageKey", GetMessageFromServerAsync);
}
}