C#中WPF内存回收与释放LierdaCracker的实现
作者:combAligadou 发布时间:2022-11-13 00:15:44
使用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
猜你喜欢
- tcp一般用于维持一个可信任的连接,比起udp更为安全可靠,在vs.net,分别有tcpclient和udpclient以及tcpliste
- 1. 前言Spring最重要的一个概念当属Bean了,我们写的Controller、Service、Dao凡是加了对应注解交给Spring管
- 本文实例讲述了C#获取web.config配置文件内容的方法。分享给大家供大家参考。具体实现方法如下:1.ConfigurationMana
- 最近碰到个需求,是希望在Unity有一个按钮,打开后直接跳转淘宝app,打开商品页面。百度了下没有相关的文章,于是我在此分享下。之前开发游戏
- 新添加个发文类型insert into mis.zyb_sf_type values('121','榆财法字'
- 使用ManagedWifi查看当前Wifi信号并选择wifiusing System;using System.Collections.Ge
- 前段时间在项目开发中,有listview实现单选和多选的效果,特别是listview的单选效果,一开始项目比较紧,自己考虑的是用listvi
- 不可变对象不可变(immutable): 即对象一旦被创建初始化后,它们的值就不能被改变,之后的每次改变都会产生一个新对象。var str=
- 类和结构是.NET Framework中的同样类型系统的两种基本构造。两者在本质上都属于数据结构,封装这一组整体作为一个逻辑单位的数据和行为
- 引言近期,Google 发布了 Android 11的平台稳定版本。Android 11 将在确保用户隐私安全的前提下,更好地让用户畅享最新
- 前言不积跬步无以至千里,不积小流,无以成江海在公司一般来说,都只会接触一些CRUD的业务,很多时候可能你想设计很多的代码结构,但是时间不允许
- 最小堆基本思想:堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的,每次都取堆
- 事务挂起和事务恢复源码解读在学习spring事务的时候,一定会涉及到一个概念,无法避免的,就是事务挂起和事务恢复对于事务挂起和事务恢复,可以
- 引言之前写了一篇关于 TraceId 的文章:为全局请求添加 TraceId ,看日志再也不懵逼今天就接着 TraceId 做一些优化,如果
- 本文实例讲述了java实现图片写入高清字体及带边框的方法。分享给大家供大家参考。具体实现方法如下:Graphics2D g2=image.c
- 之前我们在做消息回复的时候我们对回复的消息简单做了分类,前面也有讲述如何回复【普通消息类型消息】,这里将讲述多媒体消息的回复方法,【多媒体消
- 本文实例讲述了c#与js随机数生成方法。分享给大家供大家参考。具体如下:1. C#产生随机数方法:Random rd = new Rando
- 本文实例讲述了C#实现对字符串进行大小写切换的方法。分享给大家供大家参考。具体实现方法如下:C#代码如下:public class Prog
- 本文实例讲述了C#简单聊天程序实现方法。分享给大家供大家参考。具体如下:假如有服务器端程序,ChatServer和客户端程序ChatClie
- 本文实例讲述了C#手工双缓冲技术。分享给大家供大家参考。具体如下:using System;using System.Collections