網站首頁 編程語言 正文
使用wpf程序常常會出現一個問題,那就是內存占用過高,使用wpf的程序功能越復雜往往用著用著內存就本著90往上去了。
一方面wpf本身是一個ui框架,對圖像以及界面的渲染雖然提高了軟件的美觀性,但實際使用過程中調用和消耗了大量的內存來進行協同處理;
另一方面這些調用的內存的確在使用完成之后并沒有進行主動的釋放或者是只是自動釋放了一部分,即對于托管資源通過GC自動清理回收。對于非托管資源,通過代碼調用手動進行清除,再由GC回收。例如流,數據庫連接,網絡連接等,所以就需要我們主動定時的對內存進行回收釋放的處理。
在這里非常推薦使用LierdaCracker
一.可以使用nuget管理安裝Lierda.WPFHelper包,在項目的App.xaml.cs中的Application_Startup方法里實例化并調用cracker方法直接使用
LierdaCracker cracker = new LierdaCracker();
cracker.Cracker();
二.自己實現LierdaCracker類
提到C#資源和內存回收肯定少不了GC垃圾回收機制,托管堆上的內存由GC全權負責, 值引用的在棧上的內存會隨著棧空間的消亡而自動消失。
GC.Collect();
GC.WaitForPendingFinalizers();
此方法強制對所有代進行即時垃圾回收!
當應用程序代碼中某個確定的點上使用的內存量大量減少時,在這種情況下使用 GC.Collect 方法可能比較合適。而GC.WaitForPendingFinalizers則是提供收集完成前的等待。
另外一個非常重要的系統api在釋放內存的時候也是非常重要的
SetProcessWorkingSetSize,使用這個函數來設置應用程序最小和最大的運行空間,只會保留需要的內存。當應用程序被閑置或系統內存太低時,操作系統會自動調用這個機制來設置應用程序的內存。應用程序也可以使用 VirtualLock 來鎖住一定范圍的內存不被系統釋放。
事實上,使用該函數并不能提高什么性能,也不會真的節省內存。
因為他只是暫時的將應用程序占用的內存移至虛擬內存,一旦,應用程序被激活或者有操作請求時,這些內存又會被重新占用。如果你強制使用該方法來 設置程序占用的內存,那么可能在一定程度上反而會降低系統性能,因為系統需要頻繁的進行內存和硬盤間的頁面交換。
BOOL SetProcessWorkingSetSize(
HANDLE hProcess,
SIZE_T dwMinimumWorkingSetSize,
SIZE_T dwMaximumWorkingSetSize
);
將 2個 SIZE_T 參數設置為 -1 ,即可以使進程使用的內存交換到虛擬內存,只保留一小部分代碼,它是windowsNT的api 所以使用的使用需要加上平臺條件。
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
綜合下來LierdaCracker類為
?public class LierdaCracker
?{
?? ? [DllImport("kernel32.dll")]
? ? ?private static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);
?? ? private void FlushMemory()
? ? ?{
? ? ? ? ? GC.Collect();
? ? ? ? ? GC.WaitForPendingFinalizers();
? ? ? ? ? if (Environment.OSVersion.Platform == PlatformID.Win32NT)
? ? ? ? ? ? ? SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
? ? ? }
?? ? ?public void Cracker(int sleepSpan = 50)
? ? ? {
? ? ? ? ? ?_ = Task.Factory.StartNew(delegate
? ? ? ? ? ?{
? ? ? ? ? ? ? ?while (true)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?try
? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ?SetDate();
? ? ? ? ? ? ? ? ? ? ? ?FlushMemory();
? ? ? ? ? ? ? ? ? ? ? ?Thread.Sleep(TimeSpan.FromSeconds((double)sleepSpan));
? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ?catch { }
? ? ? ? ? ? ? ?}
? ? ? ? ? ?});
? ? ? ?}
?}
原文鏈接:https://blog.csdn.net/Sir_aligaduo/article/details/123396848
相關推薦
- 2022-12-01 C語言數據在內存中的存儲流程深入分析_C 語言
- 2022-05-11 如何使 React 中的 useEffect、useLayoutEffect 只調用一次
- 2022-07-13 Stream的源碼簡單解析
- 2022-06-12 C語言?智能指針?shared_ptr?和?weak_ptr_C 語言
- 2022-08-05 基于redis+lua進行限流
- 2022-09-01 一文搞懂Scrapy與MongoDB交互過程_MongoDB
- 2022-03-14 @ConfigurationProperties獲取參數值
- 2022-09-29 LyScript實現內存交換與差異對比的方法詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支