diff --git a/src/Core/Grand.Infrastructure/Caching/MemoryCacheBase.cs b/src/Core/Grand.Infrastructure/Caching/MemoryCacheBase.cs index cf4e54c61..ba132dcc9 100644 --- a/src/Core/Grand.Infrastructure/Caching/MemoryCacheBase.cs +++ b/src/Core/Grand.Infrastructure/Caching/MemoryCacheBase.cs @@ -46,7 +46,7 @@ public virtual T Get(string key, Func acquire, int cacheTime) { if (_cache.TryGetValue(key, out T cacheEntry)) return cacheEntry; var semaphore = CacheEntries.GetOrAdd(key, _ => new SemaphoreSlim(1, 1)); - semaphore.Wait(); + semaphore.Wait(CancellationToken.None); try { if (!_cache.TryGetValue(key, out cacheEntry)) diff --git a/src/Tests/Grand.Infrastructure.Tests/Caching/MemoryCacheBaseTests.cs b/src/Tests/Grand.Infrastructure.Tests/Caching/MemoryCacheBaseTests.cs index dd8c7742b..ba0676936 100644 --- a/src/Tests/Grand.Infrastructure.Tests/Caching/MemoryCacheBaseTests.cs +++ b/src/Tests/Grand.Infrastructure.Tests/Caching/MemoryCacheBaseTests.cs @@ -44,6 +44,31 @@ public void GetTest_CacheTimeMinutes() Assert.AreEqual("test", result); } + [TestMethod] + [Timeout(10000)] + public async Task Get_WhenClearCancelsWaitingSemaphore_DoesNotThrow() + { + var acquireStarted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var releaseAcquire = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + var firstRead = _service.GetAsync("key", async () => + { + acquireStarted.SetResult(true); + await releaseAcquire.Task; + return "test"; + }, 1); + + await acquireStarted.Task; + + var secondRead = Task.Run(() => _service.Get("key", () => "fallback", 1)); + + _service.Clear(false).GetAwaiter().GetResult(); + releaseAcquire.SetResult(true); + + Assert.AreEqual("test", await firstRead); + Assert.AreEqual("test", await secondRead); + } + [TestMethod] public async Task GetAsyncTest() {