WPF中解决内存泄露场的解决方法的几点提示与解决方法

【跟谁学社区】-学习论坛_学习小组_兴趣小组
话题小组123帮你解决孩子教育和妈妈成长问题NEW「职说Talk」,专属职场人学习的平台。NEW领先的高考状元培养社群。NEW外教爸爸双语宝宝让0-12岁儿童爱上英语三岁看小,七岁看老,家庭教育至关重要!这里有你想要的咨询,快来加入吧!嗨!We are 伐木累!一起打造嗨皮高中生活~~来找到与你相知的那一群人!情调的生活,钱多多的职场,都是我们的!张开梦想的翅膀,我们飞向新世界!粉丝互动、建议反馈,嗨起来~中国爱乐乐团第一小提琴手高中小海量资料,坚持看一年,英语会改变30年成就3000万人魅力表达、身心富足瑜伽,让你遇到最美丽的自己!解析高考招生政策,介绍大学和专业最简单方法。分数+ 能力,语言+ 逻辑。三分长相 七分打扮 会打扮的女人最好命!既然选择远方,便只顾风雨兼程关于日语、关于日本,一起聊聊吧每天都离法国更近一点在喧嚣的世界中打造一片心灵的净土!爱美术,爱生活每日变换自己的装束,分享你的美!蹦沙卡拉卡~帅哥美女看这里~大千世界,总有你不知道的事~热门帖子17278163222142612021102210321340001011110111000021010111...hi,欢迎来到跟谁学社区登录
关注我们官方微信关于跟谁学服务支持帮助中心WPF中解决内存泄露的几点提示与解决方法
阅读&46 收藏&0
领取地址:
推荐:[Flex内存泄露解决方法和内存释放优化原则你对Flex内存泄露的概念是否了解,这里和大家分享一下Flex内存释放优化原则和Flex内存泄露解决方法,希望本文的介绍能让你有所收
一直以来用WPF做一个项目,但是开发中途发现内存开销太大,用ANTS Memory Profiler分析时,发现在来回点几次载入页面的操作中,使得非托管内存部分开销从起始的43.59M一直到150M,而托管部分的开销也一直持高不下,即每次申请的内存在结束后不能完全释放。在网上找了不少资料,甚受益,现在修改后,再也不会出现这种现象了(或者说,即使有也不吓人),写下几个小心得:
1. 慎用WPF样式模板合并
  我发现不采用合并时,非托管内存占用率较小,只是代码的理解能力较差了,不过我们还有文档大纲可以维护。
2. WPF样式模板请共享
  共享的方式最简单不过的就是建立一个类库项目,把样式、图片、笔刷什么的,都扔进去,样式引用最好使用StaticResource,开销最小,但这样就导致了一些写作时的麻烦,即未定义样式,就不能引用样式,哪怕定义在后,引用在前都不行。
3. 慎用隐式类型var的弱引用
  这个本来应该感觉没什么问题的,可是不明的是,在实践中,发现大量采用var与老老实实的使用类型声明的弱引用对比,总是产生一些不能正确回收的WeakRefrense(这点有待探讨,因为开销不是很大,可能存在一些手工编程的问题)
4. 写一个接口约束一下
  谁申请谁释放,基本上这点能保证的话,内存基本上就能释放干净了。我是这么做的:
interface IUIElement : IDisposable
/// &summary&
/// 注册事件
/// &/summary&
void EventsRegistion();
/// &summary&
/// 解除事件注册
/// &/summary&
void EventDeregistration();
在实现上可以这样:
1 #region IUIElement 成员 2 public void EventsRegistion() 3 { 4
this.traineeReport.SelectionChanged += new SelectionChangedEventHandler(traineeReport_SelectionChanged); 5 } 6
7 public void EventDeregistration() 8 { 9
this.traineeReport.SelectionChanged -= new SelectionChangedEventHandler(traineeReport_SelectionChanged);10 }11 12 p13 14 ~TraineePaymentMgr()15 {16
ConsoleEx.Log(&{0}被销毁&, this);17
Dispose(false);18 }19 20 public void Dispose()21 {22
ConsoleEx.Log(&{0}被手动销毁&, this);23
Dispose(true);24
GC.SuppressFinalize(this);25 }26 27 protected void Dispose(bool disposing)28 {29
ConsoleEx.Log(&{0}被自动销毁&, this);30
if(!disposed)31
if(disposing)33
//托管资源释放35
((IDisposable)traineeReport).Dispose();36
((IDisposable)traineePayment).Dispose();37
//非托管资源释放39
disposed =41 }42 #endregion
&比如写一个UserControl或是一个Page时,可以参考以上代码,实现这样接口,有利于资源释放。
5. 定时回收垃圾
DispatcherTimer GCTimer = new DispatcherTimer();public MainWindow(){
InitializeComponent();
this.GCTimer.Interval = TimeSpan.FromMinutes(10); //垃圾释放定时器 我定为每十分钟释放一次,大家可根据需要修改
  this.GCTimer.start();
this.EventsRegistion();
// 注册事件}public void EventsRegistion(){
this.GCTimer.Tick += new EventHandler(OnGarbageCollection);}public void EventDeregistration(){
this.GCTimer.Tick -= new EventHandler(OnGarbageCollection);}void OnGarbageCollection(object sender, EventArgs e){
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();}
6. 较简单或可循环平铺的图片用GeometryDrawing实现
一个图片跟几行代码相比,哪个开销更少肯定不用多说了,而且这几行代码还可以BaseOn进行重用。
&DrawingGroup x:Key=&Diagonal_50px&&
&DrawingGroup.Children&
&GeometryDrawing Brush=&#FF2A2A2A& Geometry=&F1 M 0,0L 50,0L 50,50L 0,50 Z&/&
&GeometryDrawing Brush=&#FF262626& Geometry=&F1 M 50,0L 0,50L 0,25L 25,0L 50,0 Z&/&
&GeometryDrawing Brush=&#FF262626& Geometry=&F1 M 50,25L 50,50L 25,50L 50,25 Z&/&
&/DrawingGroup.Children&&/DrawingGroup&
这边是重用
&DrawingBrush x:Key=&FrameListMenuArea_Brush& Stretch=&Fill& TileMode=&Tile& Viewport=&0,0,50,50& ViewportUnits=&Absolute&
Drawing=&{StaticResource Diagonal_50px}&/&
上面几行代码相当于这个:
7. 使用Blend做样式的时候,一定要检查完成的代码
众所周知,Blend定义样式时,产生的垃圾代码还是比较多的,如果使用Blend,一定要检查生成的代码。
&推荐:[近日在项目中使用sqlite3作数据库,在开发的过程中,无论使用文件库还是内存库总会发生内存泄露的问题。经过查找及在网上寻找解决方案,总结解决方法如下:1. 在使用sqlit
8. 静态方法返回诸如List&&等变量的,请使用out
public static List&String& myMothod(){...}
public static myMothod(out List&String& result){...}
9. 打针对此问题的微软补丁
3.5的应该都有了吧,这里附上NET4的内存泄露补丁地址,&(QFE:& Hotfix request to implement hotfix KB981107 in .NET 4.0&)
这是官方给的说明,看来在样式和数据绑定部分下了点工夫啊:
运行一个包含样式或模板,请参阅通过使用 StaticResource 标记扩展或 DynamicResource 标记扩展应用程序资源的 WPF 应用程序。 创建使用这些样式或模板的多个控件。 但是,这些控件不使用引用的资源。 在这种情况的一些内存WeakReference对象和空间泄漏的控股数组后,垃圾回收释放该控件。
运行一个包含的控件的属性是数据绑定到的 WPF 应用程序DependencyObject对象。 该对象的生存期是超过控件的生存期。 许多控件时创建,一些内存WeakReference对象和容纳数组空格被泄漏后垃圾回收释放该控件。
运行使用树视图控件或控件派生于的 WPF 应用程序,选择器类。 将控件注册为控制中的键盘焦点的内部通知在KeyboardNavigation类。 该应用程序创建这些控件的很多。 例如对于您添加并删除这些控件。 在本例中为某些内存WeakReference对象和容纳数组空格被泄漏后垃圾回收释放该控件。
继续更新有关的三个8月补丁,详细的请百度:&&&&,都是NET4的补丁,在发布程序的时候,把这些补丁全给客户安装了会好的多。
10.& 对string怎么使用的建议
这个要解释话就长了,下面仅给个例子说明一下,具体的大家去找找MSDN
string ConcatString(params string[] items)
string result = &&;
foreach (string item in items)
string ConcatString2(params string[] items)
StringBuilder result = new StringBuilder();
for(int i=0, count = items.Count(); i& i++)
result.Append(items[i]);
return result.ToString();
建议在需要对string进行多次更改时(循环赋值、连接之类的),使用StringBuilder。我已经把工程里这种频繁且大量改动string的操作全部换成了StringBuilder了,用ANTS Memory Profiler分析效果显著,不仅提升了性能,而且垃圾也少了。
11. 其它用上的技术暂时还没想到,再补充...
如果严格按以上操作进行的话,可以得到一个满意的结果:
运行了三十分钟,不断的切换功能,然后休息5分钟,回头一看,结果才17M左右内存开销,效果显著吧。
然后对于调试信息的输出,我的做法是在窗体应用程序中附带一个控制台窗口,输出调试信息,给一个类,方便大家:
using Susing System.Collections.Gusing System.Lusing System.Tusing System.Runtime.InteropSnamespace Trainee.UI.UIHelper{
public struct COORD
public ushort X;
public ushort Y;
public struct CONSOLE_FONT
public COORD
public static class ConsoleEx
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32&, CharSet = CharSet.Auto)]
internal static extern bool AllocConsole();
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32&, CharSet = CharSet.Auto)]
internal static extern bool SetConsoleFont(IntPtr consoleFont, uint index);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32&, CharSet = CharSet.Auto)]
internal static extern bool GetConsoleFontInfo(IntPtr hOutput, byte bMaximize, uint count, [In, Out] CONSOLE_FONT[] consoleFont);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32&, CharSet = CharSet.Auto)]
internal static extern uint GetNumberOfConsoleFonts();
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32&, CharSet = CharSet.Auto)]
internal static extern COORD GetConsoleFontSize(IntPtr HANDLE, uint DWORD);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32.dll &)]
internal static extern IntPtr GetStdHandle(int nStdHandle);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&kernel32.dll&, CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetConsoleTitle(String sb, int capacity);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&user32.dll&, EntryPoint = &UpdateWindow&)]
internal static extern int UpdateWindow(IntPtr hwnd);
[System.Security.SuppressUnmanagedCodeSecurity]
[DllImport(&user32.dll&)]
internal static extern IntPtr FindWindow(String sClassName, String sAppName);
public static void OpenConsole()
var consoleTitle = && Debug Console&;
AllocConsole();
Console.BackgroundColor = ConsoleColor.B
Console.ForegroundColor = ConsoleColor.C
Console.WindowWidth = 80;
Console.CursorVisible =
Console.Title = consoleT
Console.WriteLine(&DEBUG CONSOLE WAIT OUTPUTING...{0} {1}\n&, DateTime.Now.ToLongTimeString());
//这里是改控制台字体大小的,可能会导致异常,在我这个项目中我懒得弄了,如果需要的的话把注释去掉就行了
//IntPtr hwnd = FindWindow(null, consoleTitle);
//IntPtr hOut = GetStdHandle(-11);
//const uint MAX_FONTS = 40;
//uint num_fonts = GetNumberOfConsoleFonts();
//if (num_fonts & MAX_FONTS) num_fonts = MAX_FONTS;
//CONSOLE_FONT[] fonts = new CONSOLE_FONT[MAX_FONTS];
//GetConsoleFontInfo(hOut, 0, num_fonts, fonts);
//for (var n = 7; n & num_ ++n)
//fonts[n].dim = GetConsoleFontSize(hOut, fonts[n].index);
//if (fonts[n].dim.X == 106 && fonts[n].dim.Y == 33)
SetConsoleFont(hOut, fonts[n].index);
UpdateWindow(hwnd);
public static void Log(String format, params object[] args)
Console.WriteLine(&[& + DateTime.Now.ToLongTimeString() + &] & + format, args);
public static void Log(Object arg)
Console.WriteLine(arg);
在程序启动时,可以用ConsoleEx.OpenConsole()打开控制台,用ConsoleEx.Log(.....)或者干脆用Console.WriteLine进行输出就可以了。推荐:[内存泄露是指程序在运行过程中动态申请的内存空间不再使用后没有及时释放,从而很可能导致应用程序内存无线增长。更广义的内存泄露包括未对系统的资源的及时释放,比如句
请输入账号
请输入密码
&下次自动登录
第三方登录
请输入邮箱
请输入密码
请输入姓名或常用昵称
同意并接受
简短推荐语
为了正常使用评论、审核、关注等功能,请激活您的账号。
您的 Email:
激活邮件已发送,请注意查收(注意检查回收站、垃圾箱中是否有激活邮件)
如果仍未收到,请尝试
,如碰到困难请没有更多推荐了,
不良信息举报
举报内容:
wpf内存泄漏问题
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!wpf窗体关闭了,如何释放使用的资源
[问题点数:20分,结帖人a]
wpf窗体关闭了,如何释放使用的资源
[问题点数:20分,结帖人a]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2012年6月 .NET技术大版内专家分月排行榜第一
匿名用户不能发表回复!|没有更多推荐了,
不良信息举报
举报内容:
WPF WPF中解决内存泄露的几点提示与解决方法
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 ios内存泄露怎么解决 的文章

 

随机推荐