Winforms:消除WebBrowser的GDI Objects泄露

WinformsWebBrowser是一个经常被使用的控件,用来浏览网页。可是很多程序员发现WebBrowser会有GDI Objects泄露。

一、 问题重现步骤

1. 新建一个Winforms项目;

2. 添加一个新Form,命名为FormWebBrowser

3. FormWebBrowser中添加一个WebBrowser,并为属性Url设置一个有效的网址;

4. 回到Form1,在上面添加一个按钮;

5. 双击按钮,进入代码编辑窗口;

6. button1Click添加事件处理器:

private void button1_Click(object sender, EventArgs e)

{

FormWebBrowser form = new FormWebBrowser();

form.ShowDialog();

}

7. 编译运行;

8. 打开任务管理器。如果进程(Processes)页面没有GDI Objects的列,点击菜单视图 View->选择列(Select Column…)。在弹出的对话框中,选择GDI Objects

9. 点击button1,这样FormWebBrowser就会弹出来。关掉FormWebBrowser,回到Form1。再点击button1。这样重复弹出FormWebBrowser再关掉。

10. 在步骤9中,注意每次关掉FormWebBrowserGDI Objects数目。我们会注意到GDI Objects数目会一直升高。这就是GDI Objects的症状。

二、 原因分析

为了正确显示网页的内容,WebBrowser会创建一些GDI的对象。GDI对象不是托管资源,因此当我们不再需要这些资源时,我们应该显示释放这些资源。WebBrowser提供了Dispose函数,在WebBrowser不再使用的时候,我们应该调用Dispose函数。

三、 建议

既然出现GDI Objects泄露的原因是没有调用WebBrowser.Dispose(),我们就应该在合适的时候调用这个方法。显然,我们在FormWebBrowser消失的时候,我们不会再使用WebBrowser,这个时候就可以调用该方法。也就是我们可以在FormWebBrowserClosed事件处理器里调用WebBrowser.Dispose

事实上Form也有Dispose方法。在Form.Dispose里,Winforms会去调用它所有子控件的Dispose方法。因此,一个更安全的办法就是当FormWebBrowser不再使用的时候,调用FormWebBrowser.Dispose

C#提供了using的关键词。使用这个关键词创建的对象,.NET会确保在这些对象不再使用的时候会调用它们的Dispose。这样会比我们自己调用Dispose会更安全。

基于上面的分析,我们建议的办法是:我们用using关键词创建FormWebBrowser对象。这样当我们关掉一个FormWebBrowser的时候,我们会确保它的Dispose会被调用。这样WebBrowserDispose也会被调用,GDI的资源也就随之释放,也就没有GDI的泄露了。

参考代码如下:

private void button1_Click(object sender, EventArgs e)

{

using (FormWebBrowser form = new FormWebBrowser())

form.ShowDialog();

}

你可能感兴趣的:(.net,浏览器,项目管理)