从异步请求返回缓存条目时锁定
Locking when returning a cache entry from a asynchronous request
我写了一个应该从网络服务获取一些信息的方法。
我想避免对服务的额外调用,所以我试图将信息放入 MemoryCache according to this post.
不同的是,我在客户端没有"SomeHeavyAndExpensiveCalculation",而是将工作委托给了网络服务。所以我想等电话。
据我所知,在当前的实现中,我可以向 Web 服务器发出多个请求,因为我无法在锁内等待请求,这就是它被移出锁的原因。
有更好的解决方案吗?
谢谢。
private static readonly object CompanyInfoLock = new object();
public async Task<CompanyDto> GetCompanyInfo()
{
const string cacheKey = "_COMPANYINFO_";
CompanyDto companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
CompanyDto company = await _userManagementService.InvokeAsync(x => x.GetCompanyAsync(AppPrincipal.Current.CurrentCompanyId));
lock (CompanyInfoLock)
{
companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
MemoryCache.Default.Add(cacheKey, company, new CacheItemPolicy
{
SlidingExpiration = new TimeSpan(2, 0, 0)
});
}
return company;
}
使用 SemaphoreSlim
以便您可以异步锁定并在调用 Web 服务之前放置锁定块。
private static readonly SemaphoreSlim CompanyInfoLock = new SemaphoreSlim (1);
public async Task<CompanyDto> GetCompanyInfo()
{
const string cacheKey = "_COMPANYINFO_";
CompanyDto companyInfo;
companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
await CompanyInfoLock.WaitAsync();
try
{
//Check a 2nd time inside the lock to see if the cache has the data.
companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
companyInfo = await _userManagementService.InvokeAsync(x => x.GetCompanyAsync(AppPrincipal.Current.CurrentCompanyId));
MemoryCache.Default.Add(cacheKey, companyInfo, new CacheItemPolicy
{
SlidingExpiration = new TimeSpan(2, 0, 0)
});
return companyInfo;
}
finally
{
CompanyInfoLock.Release();
}
}
我写了一个应该从网络服务获取一些信息的方法。 我想避免对服务的额外调用,所以我试图将信息放入 MemoryCache according to this post.
不同的是,我在客户端没有"SomeHeavyAndExpensiveCalculation",而是将工作委托给了网络服务。所以我想等电话。
据我所知,在当前的实现中,我可以向 Web 服务器发出多个请求,因为我无法在锁内等待请求,这就是它被移出锁的原因。
有更好的解决方案吗?
谢谢。
private static readonly object CompanyInfoLock = new object();
public async Task<CompanyDto> GetCompanyInfo()
{
const string cacheKey = "_COMPANYINFO_";
CompanyDto companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
CompanyDto company = await _userManagementService.InvokeAsync(x => x.GetCompanyAsync(AppPrincipal.Current.CurrentCompanyId));
lock (CompanyInfoLock)
{
companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
MemoryCache.Default.Add(cacheKey, company, new CacheItemPolicy
{
SlidingExpiration = new TimeSpan(2, 0, 0)
});
}
return company;
}
使用 SemaphoreSlim
以便您可以异步锁定并在调用 Web 服务之前放置锁定块。
private static readonly SemaphoreSlim CompanyInfoLock = new SemaphoreSlim (1);
public async Task<CompanyDto> GetCompanyInfo()
{
const string cacheKey = "_COMPANYINFO_";
CompanyDto companyInfo;
companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
await CompanyInfoLock.WaitAsync();
try
{
//Check a 2nd time inside the lock to see if the cache has the data.
companyInfo = MemoryCache.Default[cacheKey] as CompanyDto;
if (companyInfo != null) return companyInfo;
companyInfo = await _userManagementService.InvokeAsync(x => x.GetCompanyAsync(AppPrincipal.Current.CurrentCompanyId));
MemoryCache.Default.Add(cacheKey, companyInfo, new CacheItemPolicy
{
SlidingExpiration = new TimeSpan(2, 0, 0)
});
return companyInfo;
}
finally
{
CompanyInfoLock.Release();
}
}