具有异步操作的线程安全单人

问题描述 投票:0回答:1

我有一个使用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);
        }

    }
c# asp.net-mvc thread-safety singleton ninject
1个回答
0
投票

基于这个 岗位,很多人似乎都主张只使用 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);
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.