以下测试会间歇性失败。它在MemoryCache中缓存具有绝对过期时间的项目,以及在项目被移除之前应该调用的更新回调。但是有时在测试结束之前调用回调,有时甚至根本没有回调。使用MemoryCache进行测试UpdateCallback
有了足够大的缓冲时间,它总是会被调用至少一次。但是这并不符合我的目的,因为我要求缓存总是在数据过期之前尝试更新数据。
现在在我的现实世界中的场景,我不会有10秒到期时间和粒度,但它仍然困扰着我,这个测试间歇性失败。
任何人都想过为什么会发生这种情况?
注意:还间歇性地失败,60秒到期和5秒缓冲区。
using System;
using System.Runtime.Caching;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class MemoryCacheTest
{
private const double ExpiryInSeconds = 10;
private const double ExpiryBufferInSeconds = 5;
private readonly object updateItemCounterLock = new object();
private int updateItemCounter = 0;
[TestMethod]
public async Task MemoryCacheUpdateTest()
{
// Set item in cache with absolute expiration defined above
MemoryCache cache = MemoryCache.Default;
CacheItem cacheItem = new CacheItem("key", "value");
CacheItemPolicy cacheItemPolicy = new CacheItemPolicy
{
AbsoluteExpiration = DateTimeOffset.Now + TimeSpan.FromSeconds(ExpiryInSeconds),
UpdateCallback = new CacheEntryUpdateCallback(this.UpdateItem)
};
cache.Set(cacheItem, cacheItemPolicy);
// Delay for absolute expiration time + buffer
await Task.Delay(TimeSpan.FromSeconds(ExpiryInSeconds) + TimeSpan.FromSeconds(ExpiryBufferInSeconds));
// Test that the update callback was invoked once
Assert.AreEqual(1, updateItemCounter);
}
// Incrememnts the updateItemCounter
private void UpdateItem(CacheEntryUpdateArguments args)
{
lock (updateItemCounterLock)
{
updateItemCounter++;
}
}
}
如果您注意到,AbsoluteExpiration值表示物品将被驱逐的时间量。这意味着这是它保持有效的最短时间,没有(具有讽刺意味的)绝对时间。这里的绝对是指这个事实,它不是一个滑动时间限制......并不是它会在那个时刻被驱逐。基本上,该物品可以在到期后的任何时间被驱逐,这可能是几秒钟,甚至几分钟后。我的测试表明,到期时间可以在0到30秒后的任何时间发生,但可能会更长。 – 2014-12-04 06:48:28
这篇文章似乎表明,内部实现具有某种硬连线20秒计时器:http://stackoverflow.com/questions/12630168/memorycache-absoluteexpiration-acting-strange不知道这是否正确,但它肯定与我在测试结果中看到的相符。 – 2014-12-04 07:08:54