Skip to content

Instantly share code, notes, and snippets.

@tatarincev
Last active March 1, 2021 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tatarincev/4c942a7603a061d41deb393e0aa66545 to your computer and use it in GitHub Desktop.
Save tatarincev/4c942a7603a061d41deb393e0aa66545 to your computer and use it in GitHub Desktop.
The showcase for possible memory leaks if using a shared CancellationTokenSource for cached items
class Program
{
static void Main()
{
//global token source that being used for clear entire cached elements
var globalTokenSource = new CancellationTokenSource();
Action doWork = () =>
{
for (int i = 0; i < 100; i++)
{
var elementTokenSource = new CancellationTokenSource();
var options = new MemoryCacheEntryOptions();
var compositionToken = new CompositeChangeToken(new[] {
new CancellationChangeToken(elementTokenSource.Token),
new CancellationChangeToken(globalTokenSource.Token) });
options.AddExpirationToken(compositionToken);
//Intentionally set a small lifetime for cached data
options.SetAbsoluteExpiration(TimeSpan.FromTicks(1));
_memoryCache.Set(i.ToString(), "some cached data", options);
}
Thread.Sleep(1000);
//Enforce clean all data from cache
_memoryCache.Compact(1.0);
};
// Add some data into cache with shared Cancellation token
doWork();
Thread.Sleep(1000);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
//Got memory leak with stale Cancellation token registers for all cached items until we not call globalTokenSource.Dispose()
}
}
@tatarincev
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment