在多个窗口中使用WPF WebBrowser控件时内存泄漏

时间:2010-01-15 03:31:47

标签: c# wpf memory-leaks browser

我正在开发一个使用WPF WebBrowser控件(System.Windows.Controls.WebBrowser)的项目。程序的Web浏览器元素是用户可以参与的许多活动之一,并且在单独的窗口中打开。在用户离开浏览器之后,窗口关闭,每次用户返回浏览器时都会创建一个新窗口。我们注意到在我们的程序中出现了严重的内存泄漏/性能下降(在初次使用浏览器时,使用率从最初的200起大约达到700mb)。在我们自己的代码中未能找到任何资源泄漏点之后,我决定确定问题是否与我们自己的WebBrowser包装器控件或WPF控件有关。

我创建了一个新的简单项目,只包含一个MainWindow和一个WebWindow。主窗口上的一个按钮启动了一个针对gmail的浏览器(我们注意到的网站是我们检查过的少数几个问题)。关闭此窗口后,不会释放资源(任务管理器或Process Explorer中的VM大小没有减少),并且进程处理的GDI对象数量不会减少(程序以~30开始,打开浏览器需要它到~140,关闭浏览器后~140仍然打开)。打开另一个浏览器会导致更多句柄,并分配更多资源。此外,通过在WebBrowser控件上专门调用Dispose()无法解决此问题。代码很简单,如下:

主窗口:

<Window x:Class="WebBrowserMemory.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
            <Button Click="Button_Click">Gmail</Button>
        </StackPanel>
    </Grid>
</Window>

Button_Click:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var win = new WebWindow();
    win.Show();
    win.Browser.Navigate("http://www.gmail.com");
}

网络窗口:

<Window x:Class="WebBrowserMemory.WebWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WebWindow" Height="300" Width="300">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <WebBrowser Grid.Row="0" x:Name="_browser" />
    <Button Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10" Padding="10" Click="Button_Click">Close</Button>
</Grid>
</Window>

相关守则:

public WebBrowser Browser {
    get { return _browser; }
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    Close();
}

protected override void OnClosed(EventArgs e)
        {
            _browser.Dispose();
            base.OnClosed(e);
        }

有没有其他人使用WPF WebBrowser控件遇到此问题?

[更新:根据itowlson的回答更新帖子以指示Dispose()调用 - 即使在Web浏览器控件上调用Dispose()也不会释放资源]

3 个答案:

答案 0 :(得分:8)

与大多数WPF控件不同,WebBrowser(因为它继承自HwndHost)是IDisposable并封装非托管资源。与WinForms表单不同,WPF窗口会自动处理其子节点(因为本机WPF控件不会封装非托管资源,也不需要处理)。

向窗口添加OnClosed覆盖(或处理Closed事件),并在WebBrowser控件上调用Dispose。

答案 1 :(得分:1)

我们改为使用WinForm WebBrowser控件,它是在WPF中的FormsHost中创建的,但是从UI的角度来看两者的工作方式都相同,但我们发现WinForms的WebBrowser与WPF中的相比具有更好的功能和更好的性能

你可以手动处理WinForm控件的WebBrowser,它肯定会处理它的所有子节点并相应地释放资源,但是根据我以前的经验,WinForm的WebBrowser在关闭后不会释放100%的资源,但是它会好得多。 WPF。

答案 2 :(得分:1)

我无法完全解决泄漏,但是,我注意到在处理之前将浏览器导航到“about:blank”肯定有助于减少挂起的内存量。