分析一个错误使用MemoryCache导致的BUG
這個(gè)Bug是我在項(xiàng)目中發(fā)現(xiàn)的,原因是MemoryCache使用不當(dāng)造成了一個(gè)不小的Bug,雖說這個(gè)Bug很大部分人都知道,但是我覺得還是分享出來,記錄一下。廢話不多說,我們來看一下出錯(cuò)的代碼(代碼已經(jīng)經(jīng)過脫敏處理)
await using var services = new ServiceCollection().AddMemoryCache().BuildServiceProvider(); GetValidValues(5).Dump(); GetValidValues(8).Dump(); List<int> GetValidValues(int valueInt) {var memoryCache = services.GetRequiredService<IMemoryCache>();var vs= memoryCache.GetOrCreate("t1", entry =>{return Enumerable.Range(1, 10).ToList();});vs.RemoveAll(x => x > valueInt);return vs; }代碼中Dump是擴(kuò)展方法,它是把list內(nèi)的元素輸出出來,具體實(shí)現(xiàn)代碼如下:
public static void Dump(this List<int> vs) {string v= string.Join("--", vs);Console.WriteLine(v); }好了,來想一下上面的輸出結(jié)果會(huì)是什么吧,期望的結(jié)果應(yīng)該是每次都輸出小于等于輸入的值,實(shí)際是什么樣的呢?實(shí)際輸出結(jié)果如下:
 從上圖中第二次輸出的結(jié)果是不是和你想的不一樣呢,之所以出現(xiàn)上面問題是因?yàn)镸emoryCache對(duì)象是直接保存在內(nèi)存中的,緩存不變化時(shí)每次都返回同一個(gè)對(duì)象,如果發(fā)生了修改那么再次獲取就是修改后的內(nèi)容。因此正確做法是返回一個(gè)新對(duì)象而不是修改原來的對(duì)象,一個(gè)修改方法如下:
修改后的輸出結(jié)果如下:
 
 總結(jié):
 MemoryCache背后其實(shí)就是ConcurrentDictionary,value其實(shí)是帶著過期時(shí)間的CacheEntry,因此
 在不過期并且沒有發(fā)生變化的時(shí)候每次返回都是同一個(gè)緩存對(duì)象。作為緩存對(duì)象應(yīng)進(jìn)行只讀操作,不應(yīng)修改緩存對(duì)象,如需要修改應(yīng)創(chuàng)建新對(duì)象而不是使用原來的對(duì)象。
總結(jié)
以上是生活随笔為你收集整理的分析一个错误使用MemoryCache导致的BUG的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: OSPF区域认证配置实验
 - 下一篇: 使用JavaScript创建音乐播放器的