WPF WebBrowser Memory Leak 问题及临时解决方法
首先介绍一下内存泄漏(Memory Leak)的概念,内存泄露是指程序中已动态分配的堆内存由于某种原因未释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
最近在使用WPF WebBrowser时,就遇到了Memory Leak的问题。
在主窗体上通过一个按钮点击事件加载包含有WebBrowser控件的窗体,使用这个WebBrowser来浏览网页,然后调用WebBrowser的Dispose()方法,然后调用GC.Collect(),最后关闭当前包含有WebBrowser控件的窗体。
通过下面的代码和步骤来还原这个问题。
MainWindow.xaml
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Button Content="Launch Browser Window" x:Name="btnLaunchNewWindow" Margin="5,0,5,0" Click="btnLaunchNewWindow_Click" />
<Button Content="Force Garbage Collection" x:Name="btnForceGarbageCollection" Click="btnForceGarbageCollection_Click" />
<Button Content="Quit" x:Name="btnQuit" Click="btnQuit_Click" />
</StackPanel>
private void btnLaunchNewWindow_Click(object sender, RoutedEventArgs e)
{
new BrowserWindow().Show();
} private void btnForceGarbageCollection_Click(object sender, RoutedEventArgs e)
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
} private void btnQuit_Click(object sender, RoutedEventArgs e)
{
Environment.Exit();
}
BrowserWindow.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions> <StackPanel Orientation="Horizontal">
<Label Content="URL:" />
<TextBox x:Name="txtURL" Width="400" />
</StackPanel> <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,10">
<Button Content="1. Go/Navigate" x:Name="btnGo" Click="btnGo_Click" />
<Button Content="2. Dispose" x:Name="btnClose" Click="btnClose_Click" Margin="10,0" />
<Button Content="3. Force Garbage Collection" x:Name="btnForceGarbageCollection" Click="btnForceGarbageCollection_Click" />
<Button Content="4. Close Window" x:Name="closeWindow" Click="closeWindow_Click" Margin="10,0" />
</StackPanel> <WebBrowser Grid.Row="2" x:Name="webBrowser" />
</Grid>
private void btnGo_Click(object sender, RoutedEventArgs e)
{
try
{
webBrowser.Navigate(new Uri(txtURL.Text));
}
catch (Exception ex)
{
MessageBox.Show("Exception: " + ex.Message);
}
} private void btnClose_Click(object sender, RoutedEventArgs e)
{
webBrowser.Dispose();
} private void btnForceGarbageCollection_Click(object sender, RoutedEventArgs e)
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
} private void closeWindow_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
问题重现步骤:
Step1: 启动程序
Step2: “Launch Browser Window”
Step3: 在地址栏输入 http://www.msn.com (其他网址也可以)
Step4: 点击“1. Go/Navigate” button,
Step5: 当网页加载成功后,点击 “2. Dispose”
Step6: 点击 ”3. Force Garbage Collection”
Step7: 点击“4. Close Window”
重复Step2--Step7 20-25次。
多次测试后的结果如下:
在Step1程序启动后,内存占用在20M左右(不同的机器会有一些差别),

重复Step2--Step7 20-25次之后,程序的内存在130M左右,并且长时间等待不释放。

很不幸运的遇到一个内存泄露的问题。
和大多数WPF控件不一样,WebBrowser控件继承自HwndHost,使用的是非托管的资源,所以对WebBrowser进行Dispose()操作并不管用。
第一种解决方法:
早前使用过WinForm的WebBrowser控件,不存在内存泄露的问题,所以决定使用WinForm的WebBrowser代替WPF的。关于如何在WPF中承载WinForm控件,请参考https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/walkthrough-hosting-a-windows-forms-control-in-wpf
第二种解决方法:
依然使用WPF WebBrowser,但是将第二个页面(BrowserWindow.xaml)单独成一个exe。通过主程序去调用,这样当网页浏览完毕后,关闭WebBrowser所在exe,它所关联的内存全部被释放掉了。如果两个程序之间需要通信或者交换数据,可以选用WCF/命名管道等方式。
参考链接:
https://stackoverflow.com/questions/2069314/memory-leak-when-using-wpf-webbrowser-control-in-multiple-windows
https://stackoverflow.com/questions/8302933/how-to-get-around-the-memory-leak-in-the-net-webbrowser-control
WPF WebBrowser Memory Leak 问题及临时解决方法的更多相关文章
- WP_Image_Editor_Imagick 漏洞临时解决方法
导读 阿里云推送的一条短信通知:存放在上面的WordPress程序有WP_Image_Editor_Imagick漏洞问题,需要登入后台补丁等等的暗示.当然,如果需要在线补丁则需要升级阿里云的安骑士专 ...
- Myeclipse运行报错:an out of memory error has occurred的解决方法
不知道怎么了,重装的myeclipse2013,里边就放了一个项目,启动myeclipse就报 an out of memory error has occurred....... 一点yes就退出 ...
- (转)苹果iOS开发者账号过期临时解决方法
苹果iOS开发者账号过期临时解决办法 苹果iOS开发者账号一年的费用是99美金,作者最近由于各种原因,导致renew没能在账号过期之前支付好,所以在账号过期等待renew的期间,试了试一些非正常手段, ...
- Win 8下Rime输入法无法同步的临时解决方法
意外发现了Rime输入法(OS X上叫鼠须管'Squirrel',windows上叫小狼毫'Weasel',linux上叫中州韵'ibus-rime',连名字都起的这么牛逼),真是神器啊,流畅的速度, ...
- 使用dnspod遭遇的奇特问题以及背后的原因与临时解决方法
由于园子里有不少用户在使用dnspod,我们觉得有必要将这两天blogjava.net域名在dsnpod遇到的奇特问题分享一下,以免再有人踩着这个坑. 12月11日,我们登录到dnspod的后台时,大 ...
- wordpress后台打开缓慢的临时解决方法
解决方法是添加下面的主题在目前的代码在functions.php: //禁用Open Sans class Disable_Google_Fonts { public function __const ...
- Openwrt flash 空间不足的临时解决方法
最近有网友在安装软件的时候发现flash空间不够用了: 一个临时的解决方案是在RAM里面使用这个程序.因为 1.路由器改机后的RAM有64MB,flash一般有16MB,RAM空间比较大./tmp是挂 ...
- jQuery中的bind绑定事件与文本框改变事件的临时解决方法
暂时没有想到什么好的解决办法,我现在加了个浏览器判断非ie的话就注册blur事件,这样有个问题就是blur实在别的控件活动焦点的时候,txtStation控件注册的方法是为了填充它紧挨着的一个下拉列表 ...
- wpf软件某些分辨率下文字模糊解决方法
软件测试过程中发现在一台1600*900的分辨率电脑上文字模糊,甚至某些个文字出现压缩扭曲 经过实践,发现按下面方法能解决一点问题: 在窗口或控件上设置字体属性就可以了,如下: <UserCon ...
随机推荐
- Github 开源:升讯威 Winform 开源控件库( Sheng.Winform.Controls)
Github 地址:https://github.com/iccb1013/Sheng.Winform.Controls 本控件库中的代码大约写于10年前(2007年左右),难免有不成熟与欠考虑之处, ...
- 关于php内存释放问题 内存溢出问题(二)
今天抽了一上午时间,来看了看之前解决过内存问题的代码,相对来说,我对自己代码的优化程序非常不满意,一次性导入四万条数据就使代码变得如此繁琐,我想这不是根本的解决方法.通过网上检索,对问题有进一步的分析 ...
- css颜色值设置方式有哪些?以及如何随机一个颜色?
网页中颜色的使用方式有一下几种 1.颜色名称 ,如red black white 2.十六进制颜色,网页中常用,每两位代表红绿蓝的值的比例, 如 #ffffff白色 #000000黑色 3.r ...
- WPF中用户控件对比自定义控件(UserControl VS CustomControl)
接着这篇文章(http://www.cnblogs.com/shiyue/archive/2013/02/02/2889907.html)写: 用户控件(组合) 用于在一个项目中使用多次 自定义控件( ...
- Spring学习(1)----入门学习(附spring-framework下载地址)
(一)Spring是什么 Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但现在已经不止应用于企业应用 是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架- 从大小和开销 ...
- 安装并配置Apache
从今天开始,我将开始Web开发的学习.本系列博客将陆续记录我学习过程中的收获和困惑,从前端到后端,一探Web开发的流程和内容.我目前掌握的有C/C++,有一些使用C进行嵌入式开发的经验,C++就马马虎 ...
- Nginx下支持ThinkPHP的Pathinfo和URl Rewrite模式
下面介绍如何使Nginx支持ThinkPHP的Pathinfo和URL Rewrite模式. 1.ThinkPHP给出了ThinkPHP的官方解决方案,如下: 打开Nginx的配置文件 /etc/ng ...
- 将angular-ui-bootstrap的弹出框定义成一个服务的实践
定义一个弹出框的服务:alert_boxdefiine(["app"],function(mainapp){ mainapp.controller('ModalInstanceCt ...
- IBM的人工智能“沃森”首次确诊罕见白血病,只用了10分钟!
患者为一名60岁的女性,最初根据诊断结果,显示她患了急髓白血病.但在经历各种疗法后,效果并不明显. 根据东大医学院研究人员Arinobu Tojo的说法,他们利用Watson系统来对此病人进行诊断.系 ...
- 基于Mac制作iPhone铃声教程,iTunes定制铃声
前言: 网上太多制作方法了,不管是借助第三方软件还是基于iTunes的,不过这些方法都太旧了,有时看起来 ,界面的变化或其他原因,导致很不爽. 正好记录下我最近使用的一种方法: 正文: 一.下载你需要 ...