Question

I don't understand how sliding expiration is supposed to work in System.Runtime.Caching.MemoryCache with .NET 4.0.

According to the documentation, the expiring timespan is "A span of time within which a cache entry must be accessed before the cache entry is evicted from the cache."

However the following unit test fails:

private const string AnyKey = "key";
private const string AnyValue = "value";

private readonly TimeSpan timeout = TimeSpan.FromSeconds(0.5);

private void WaitSixtyPercentOfTheTimeout()
{
    Thread.Sleep(TimeSpan.FromSeconds(timeout.TotalSeconds*0.6));
}

[Test]
public void Get_RefreshesTimeoutOfSlidingExpiration()
{
    var cache = MemoryCache.Default;
    cache.Set(AnyKey, AnyValue, new CacheItemPolicy {SlidingExpiration = timeout});

    WaitSixtyPercentOfTheTimeout();
    cache[AnyKey].Should().Be(AnyValue);
    WaitSixtyPercentOfTheTimeout();

    cache[AnyKey].Should().Be(AnyValue);
}

private void UpdateCallback(CacheEntryUpdateArguments arguments)
{
}

Per coincidence, I made a small change which fixed this issue. However, does anybody now if it is a bug or a feature?

Once, the UpdateCallBack is set, expiration works as expected:

// [...]

[Test]
public void Get_RefreshesTimeoutOfSlidingExpiration()
{
    var cache = MemoryCache.Default;
    cache.Set(AnyKey, AnyValue, new CacheItemPolicy {SlidingExpiration = timeout, UpdateCallback = UpdateCallback});

    WaitSixtyPercentOfTheTimeout();
    cache[AnyKey].Should().Be(AnyValue);
    WaitSixtyPercentOfTheTimeout();

    cache[AnyKey].Should().Be(AnyValue);
}

private void UpdateCallback(CacheEntryUpdateArguments arguments)
{
}
Was it helpful?

Solution

Make the timeout longer seems to fix the problem. Make it 2 seconds works on my machine:

private readonly TimeSpan timeout = TimeSpan.FromSeconds(2);

I guess the current caching mechanism is not very accurate in timing, but in practice you wouldn't keep cache for half a second anyway.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top