C#中WPF內存回收與釋放LierdaCracker的實現

使用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 { }
               }
           });
       }

 }

到此這篇關於C#中WPF內存回收與釋放LierdaCracker的實現的文章就介紹到這瞭,更多相關C# WPF內存回收與釋放 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: