繼上次記一次w3wp占用CPU過高的解決過程(Dictionary和線程安全)后又再次與Dictionary博弈,這一次是在EntityFramework中的Dictionary。
從一個異常說起
這個異常與上次的異常有着同一個特性:間歇性,碰到類似的異常在信心上就被削弱了一大半。。。
在第一次看到這個異常的時候覺得解決它非常的簡單,無非就是在字典操作的地方加個鎖,但仔細看了一會發現這個問題並沒有那么簡單,可以看到這個異常的最后幾個堆棧信息來自System.Data.Entity命名空間,也就是EntityFramework,這就使問題變得難以尋糾。
出錯的地方就在FirstOrDefault,一個在簡單不過的Linq方法。
反編譯查看EntityFramework的實現
AddNewRelation方法的內容如下:
馬上鎖定了AddRelationshipEntryToDictionary,方法代碼如下:
可以看出是EntityFramework添加狀態監控相關的邏輯,看到這也大概猜出來了又是線程安全的問題,但為了確定我追糾了調用AddNewRelation的HandleRelationshipSpan方法。
代碼比較復雜,較難看懂,於是就去EntityFramework源碼托管的站上面去看看是否有寫注釋,碰碰運氣。
果不其然還是存在比較詳盡的注釋
問題也大致清晰了,應該是線程共享的DbContext出現了問題。
用Demo還原異常
解決方案
因為我們並不想放棄線程內共享一個DbContext的方案,所以我們並沒有從根本解決這個問題,我們把調用FirstOrDefault的操作放在了Lazy里面。
剩下的就是觀察效果。
寫在最后
寫了兩篇解決BUG的紀要不為了大家能快速解決問題,而為了交流一種尋找BUG解決BUG的思路與方法。
最后,福州地區有需要找工作或者想換工作的“猿”嗎?如果有可以溝通溝通聯系聯系唄。