I'm trying to create a pool of connections to a third-party API, and have connections expire after an interval if they are not in use. When they expire, they need to be disconnected via the third-party API.
It appeared that MemoryCache (System.Runtime.Caching) would handle this. UpdateCallback seems to behave oddly, though.
A simple LINQPad example:
void Main()
{
var cache = MemoryCache.Default;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(1);
policy.UpdateCallback = Update;
cache.Set("figkey", "fig", policy);
Thread.Sleep(2000);
object result = cache.Get("figkey");
Console.WriteLine(result == null ? "null" : result);
}
public static void Update(CacheEntryUpdateArguments arguments)
{
Console.WriteLine("got here");
}
If I run this, the output is:
fig
It does NOT output "got here".
If I comment out the line that starts with policy.UpdateCallback
, the output is:
null
What am I doing wrong?
If there's a better way to accomplish my task, I'm open to alternative suggestions.
I Think that the problem may be the Thread.Sleep
because that also blocks the cache, as they run in the same thread. If you try to make dummy loops you will se that the update handler is triggered:
var i = 0;
for (var j = 0; j < 10000000; j++)
{
for (var k = 0; k < 1000000; k++)
i++;
i--;
}
Console.WriteLine(i);
Instead of the sleep.
Just add Console.ReadLine() at the end of Main or replace Sleep with Console.ReadLine(), start your sample and wait about 10 seconds. You'll get the expected message. The timer inside MemoryCache is a bit slow.
But anyway, there certainly is a bug in MemoryCache: assigning UpdateCallback changes the behaviour, but it shouldn't.
In case if AbsoluteExpiration is set and the time is passed the method Get must return null without a dependency on existence of UpdateCallback.
BTW, RemovedCallback doesn't change the behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With