c# - 如何将异步与锁定结合起来?

标签 c# asp.net .net asynchronous

正如著名的blog post from Stephen Cleary所规定的那样,永远不要尝试同步运行异步代码(例如,通过Task.RunSynchronously()或访问Task.Result)。另一方面,您不能在lock语句中使用async/await。
我的用例是ASP.NET Core应用程序,它使用IMemoryCache缓存一些数据。现在,当数据不可用时(例如删除缓存),我必须重新填充它,应该使用lock保护它。

public TItem Get<TItem>(object key, Func<TItem> factory)
{
    if (!_memoryCache.TryGetValue(key, out TItem value))
    {
        lock (_locker)
        {
            if (!_memoryCache.TryGetValue(key, out value))
            {
                value = factory();
                Set(key, value);
            }
        }
    }
    return value;
}
在此示例中,工厂功能不能异步!如果必须异步该怎么办?

最佳答案

协调对共享变量的异步访问的一种简单方法是使用 SemaphoreSlim 。您调用WaitAsync开始异步锁定,并调用Release结束异步锁定。
例如。

private static readonly SemaphoreSlim _cachedCustomersAsyncLock = new SemaphoreSlim(1, 1);
private static ICollection<Customer> _cachedCustomers;

private async Task<ICollection<Customer>> GetCustomers()
{
    if (_cachedCustomers is null)
    {
        await _cachedCustomersAsyncLock.WaitAsync();

        try
        {
            if (_cachedCustomers is null)
            {
                _cachedCustomers = GetCustomersFromDatabase();
            }
        }
        finally
        {
            _cachedCustomersAsyncLock.Release();
        }
    }

    return _cachedCustomers;
}

关于c# - 如何将异步与锁定结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44269412/

相关文章:

c# - 视觉 C# Express 2010 : how to set language to C# 2. 0

asp.net - Azure Redis 缓存的 session 状态不适用于多个实例

c# - 将多个复选框列表值更新到 SQL DB asp.net C#

c# - 忽略 Controller 参数缺失引起的异常

c# - 我可以使用 NUnit3 控制台覆盖并行运行的测试实例的数量吗

c# - ReactiveUI:R/W 属性与输出属性

c# - 请求访问 token 时通过 OAuth 2、 "invalid_request"连接到 Google

c# - wsdl.exe 结果为 "SOAP 1.1 binding was not found"

c# - 是否可以从 .NET 核心在 linux 平台上调用共享库 (.so)?

c# - 如何通过 .NET API 打开 AutoCAD 2015