[英]Memory leak when using WPF WebBrowser control in multiple windows
我正在開發一個使用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()也不會釋放資源]
與大多數WPF控件不同,WebBrowser(因為它繼承自HwndHost)是IDisposable並封裝非托管資源。 與WinForms表單不同,WPF窗口不會自動處理其子項(因為本機WPF控件不會封裝非托管資源,也不需要處理)。
向窗口添加OnClosed覆蓋(或處理Closed事件),並在WebBrowser控件上調用Dispose。
我無法完全解決泄漏,但是,我注意到在處理之前將瀏覽器導航到“about:blank”肯定有助於減少掛起的內存量。
我們改為使用WinForm WebBrowser控件,它是在WPF中的FormsHost中創建的,但是從UI的角度來看兩者的工作方式完全相同,但是我們發現WinForms的WebBrowser與WPF中提供的功能相比具有更好的功能和更好的性能。
你可以手動配置WinForm控件的WebBrowser,它肯定會處理它的所有子節點和相應的免費資源,但是根據我以前的經驗,WinForm的WebBrowser在關閉后不會釋放100%的資源,但是它比WPF好得多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.