服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - .NET MemoryCache如何清除全部缓存

.NET MemoryCache如何清除全部缓存

2022-12-13 13:49Agile.Zhou C#

本文主要介绍了.NET MemoryCache如何清除全部缓存,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

最近有个需求需要定时清理服务器上所有的缓存。本来以为很简单的调用一下 MemoryCache.Clear 方法就完事了。谁知道 MemoryCache 类以及 IMemoryCache 扩展方法都没有 Clear 方法。这可给难住了,于是想找到所有的 Keys 来一个个 Remove ,谁知道居然也没有获取所有 Key 的方法。于是研究了一下 ,找到一些方法,下面介绍两个方法:

自定义 CacheWrapper 包装类

MemoryCache 构造 Entry 的时候支持传入 CancellationChangeToken 对象,当 CancellationChangeToken.Cancel 触发的时候会自动使该对象过期。那么我们只要对 MemoryCache 类包装一下很容易实现一个自己的 Cache 类。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CacheWrapper
   {
       private readonly IMemoryCache _memoryCache;
       private CancellationTokenSource _resetCacheToken = new();
 
       public CacheWrapper(IMemoryCache memoryCache)
       {
           _memoryCache = memoryCache;
       }
 
       public void Add(object key, object value, MemoryCacheEntryOptions memoryCacheEntryOptions)
       {
           using var entry = _memoryCache.CreateEntry(key);
           entry.SetOptions(memoryCacheEntryOptions);
           entry.Value = value;
 
           // add an expiration token that allows us to clear the entire cache with a single method call
           entry.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));
       }
 
       public object Get(object key)
       {
           return _memoryCache.Get(key);
       }
 
       public void Remove(object key)
       {
           _memoryCache.Remove(key);
       }
 
       public void Clear()
       {
           _resetCacheToken.Cancel(); // this triggers the CancellationChangeToken to expire every item from cache
 
           _resetCacheToken.Dispose(); // dispose the current cancellation token source and create a new one
           _resetCacheToken = new CancellationTokenSource();
       }
   }

然后单元测试测试一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[TestMethod()]
public void ClearTest()
{
    var memCache = new MemoryCache(new MemoryCacheOptions());
    var wrapper = new CacheWrapper(memCache);
 
    for (int i = 0; i < 10; i++)
    {
        wrapper.Add(i.ToString(), new object(), new MemoryCacheEntryOptions());
    }
 
    Assert.IsNotNull(wrapper.Get("1"));
    Assert.IsNotNull(wrapper.Get("9"));
 
    wrapper.Clear();
 
    for (int i = 0; i < 10; i++)
    {
        Assert.IsNull(wrapper.Get(i.ToString()));
    }
 
    for (int i = 0; i < 10; i++)
    {
        wrapper.Add(i.ToString(), new object(), new MemoryCacheEntryOptions());
    }
 
    Assert.IsNotNull(wrapper.Get("1"));
    Assert.IsNotNull(wrapper.Get("9"));
 
    wrapper.Clear();
 
    for (int i = 0; i < 10; i++)
    {
        Assert.IsNull(wrapper.Get(i.ToString()));
    }
 
}

测试通过。

Compact 方法

以上 CacheWrapper 类虽然可以实现我们想要的功能,但是对于原来的程序有侵入,需要使用 CacheWrapper 类替换默认的 MemoryCache 类,不是太好。于是不死心继续研究,后来直接看了 MemoryCache 的代码(源码在这),开源真香。发现 MemoryCache 有个 Compact 方法好像在干删除的勾当。也怪我英文不好,这单词是压缩的意思,居然才发现。。。。于是我们的清除所有对象的需求不就轻而易举了么?

?
1
2
3
4
5
6
7
8
/// Remove at least the given percentage (0.10 for 10%) of the total entries (or estimated memory?), according to the following policy:
        /// 1. Remove all expired items.
        /// 2. Bucket by CacheItemPriority.
        /// 3. Least recently used objects.
        /// ?. Items with the soonest absolute expiration.
        /// ?. Items with the soonest sliding expiration.
        /// ?. Larger objects - estimated by object graph size, inaccurate.
MemoryCache.Compact(double percentage);

Compact 方法会对缓存的对象进行压缩,参数是个double,0.1 表示压缩 10% ,那么传 1.0 就是压缩 100%,那不就是 Clear All 么。所以我可以使用 Compact(1.0) 来清除所有的缓存对象。单元测试跑一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[TestMethod()]
        public void CompactTest()
        {
            var memCache = new MemoryCache(new MemoryCacheOptions());
 
            for (int i = 0; i < 10; i++)
            {
                memCache.Set(i.ToString(), new object(), new MemoryCacheEntryOptions());
            }
 
            Assert.IsNotNull(memCache.Get("1"));
            Assert.IsNotNull(memCache.Get("9"));
 
            memCache.Compact(1);
 
            for (int i = 0; i < 10; i++)
            {
                Assert.IsNull(memCache.Get(i.ToString()));
            }
 
            for (int i = 0; i < 10; i++)
            {
                memCache.Set(i.ToString(), new object(), new MemoryCacheEntryOptions());
            }
 
            Assert.IsNotNull(memCache.Get("1"));
            Assert.IsNotNull(memCache.Get("9"));
 
            memCache.Compact(1);
 
            for (int i = 0; i < 10; i++)
            {
                Assert.IsNull(memCache.Get(i.ToString()));
            }
        }

完美通过。

这里简单介绍下 Compact 方法。根据注释它会按照已下优先级删除对象:

  • 过期的对象
  • CacheItemPriority 设置的优先级,等级越高越不容易被删除
  • 最近最少被使用的对象
  • 绝对过期时间
  • 滑动过期时间
  • 大对象

到此这篇关于.NET MemoryCache如何清除全部缓存的文章就介绍到这了,更多相关.NET MemoryCache清除缓存内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/kklldog/p/how-clear-all-memory-cache.html

延伸 · 阅读

精彩推荐
  • C#C#9.0 新特性简介

    C#9.0 新特性简介

    这篇文章主要介绍了C#9.0 新特性简介,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来...

    码农阿宇11202022-10-11
  • C#C#高性能动态获取对象属性值的步骤

    C#高性能动态获取对象属性值的步骤

    这篇文章主要介绍了C#高性能动态获取对象属性值的步骤,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...

    ZKEASOFT11152022-10-21
  • C#C# 使用 log4net 日志组件的方法

    C# 使用 log4net 日志组件的方法

    这篇文章主要介绍了C# 使用 log4net 日志组件的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...

    Dwaynerbing4052022-10-26
  • C#解析c# yield关键字

    解析c# yield关键字

    这篇文章主要介绍了c# yield关键字的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    八英里7892022-09-29
  • C#一篇文章说通C#中的异步迭代器

    一篇文章说通C#中的异步迭代器

    这篇文章主要给大家介绍了如何通过一篇文章说通C#中的异步迭代器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    老王Plus的老王8892022-10-24
  • C#C# 设计模式系列教程-抽象工厂模式

    C# 设计模式系列教程-抽象工厂模式

    抽象工厂模式为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。...

    Wang Juqiang10882021-11-23
  • C#浅析C# 索引器(Indexer)

    浅析C# 索引器(Indexer)

    这篇文章主要介绍了C# 索引器(Indexer)的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    菜鸟教程5592022-09-23
  • C#C语言使用getch()读取方向键

    C语言使用getch()读取方向键

    getch()是编程中所用的函数,这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车,有的C语言命令行程序会用到此函数做游戏...

    天岁3602022-11-24