【问题标题】:Locking when returning a cache entry from a asynchronous request从异步请求返回缓存条目时锁定
【发布时间】:2016-02-18 15:50:16
【问题描述】:

我编写了一个从 Web 服务获取一些信息的方法。 我想避免对服务的额外调用,所以我试图将信息放入 MemoryCache according to this post

不同之处在于我在客户端没有“SomeHeavyAndExpensiveCalculation”,但我将工作委托给 Web 服务。所以我想等电话。

据我了解,对于当前的实现,我可以向 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;
                }

【问题讨论】:

标签: c# web-services locking async-await memorycache


【解决方案1】:

使用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();
    }
}

【讨论】:

  • 我认为这种技术被称为双重检查锁定,实际上它不是线程安全的,至少对于普通锁定来说是这样。不知道 SemaphoreSlim 是否更好
猜你喜欢
  • 1970-01-01
  • 2020-06-14
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
相关资源
最近更新 更多