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

C# 在多个窗口中使用WPF WebBrowser控件时内存泄漏,c#,wpf,memory-leaks,browser,C#,Wpf,Memory Leaks,Browser,我正在从事一个使用WPF WebBrowser控件(System.Windows.Controls.WebBrowser)的项目。该程序的web浏览器元素是用户可以参与的众多活动之一,并在单独的窗口中打开。用户离开浏览器后,窗口将关闭,并且每次用户返回浏览器时都会创建一个新窗口。我们注意到,在继续使用浏览器时,我们的程序中出现了严重的内存泄漏/性能降级(使用量从最初的约200 MB增加到约700mb)。在我们自己的代码中找不到任何资源泄漏点之后,我决定确定问题是出在我们自己的WebBrowser

我正在从事一个使用WPF WebBrowser控件(System.Windows.Controls.WebBrowser)的项目。该程序的web浏览器元素是用户可以参与的众多活动之一,并在单独的窗口中打开。用户离开浏览器后,窗口将关闭,并且每次用户返回浏览器时都会创建一个新窗口。我们注意到,在继续使用浏览器时,我们的程序中出现了严重的内存泄漏/性能降级(使用量从最初的约200 MB增加到约700mb)。在我们自己的代码中找不到任何资源泄漏点之后,我决定确定问题是出在我们自己的WebBrowser包装控件还是WPF控件上

我创建了一个新的简单项目,它只包含一个MainWindow和一个WebWindow。主窗口上的一个按钮会启动一个指向gmail的浏览器(我们注意到的是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>
网络窗口:

<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>
是否有其他人在使用WPF WebBrowser控件时遇到此问题


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

与大多数WPF控件不同,WebBrowser(因为它从HwndHost继承)是IDisposable的,并且封装了非托管资源。与WinForms窗体不同,WPF窗口不会自动处置其子项(因为本机WPF控件不封装非托管资源,也不需要处置)


将OnClosed覆盖添加到窗口(或处理关闭的事件),并调用WebBrowser控件上的Dispose。

我们使用WinForm WebBrowser控件,该控件是在WPF中的FormsHost内部创建的,但是从UI的角度看,两者的工作原理基本相同,但我们发现WinForms的WebBrowser与WPF中的WebBrowser相比具有更好的功能和性能


您可以手动处理WinForm控件的WebBrowser,该控件肯定会相应地处理其所有子控件和可用资源,但是根据我过去的经验,WinForm的WebBrowser在关闭后不会释放100%的资源,但确实比WPF好得多。

但是,我还不能完全解决泄漏问题,我已经注意到,在处理之前将浏览器导航到“about:blank”肯定有助于减少内存量

抱歉,忘记了Dispose,我正在处理的实际项目确实调用了Dispose方法,我只是忘了将其添加到我的演示应用程序中。不幸的是,显式调用Dispose并不能解决问题。少数GDI句柄被释放,但绝大多数保持打开状态。更新了我的帖子,指出Dispose()被显式调用,据我所知它仍然存在。我开始使用Gecko包装器,并打算在将来用Awesomium替换该组件。我遇到了同样的问题,但仍然找不到解决方案。有什么想法吗?看。
<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);
        }