Skip to content

Commit

Permalink
Add IsDisposed checks
Browse files Browse the repository at this point in the history
Resolves cefsharp#1307
  • Loading branch information
amaitland committed Oct 13, 2015
1 parent 4ba7e95 commit 7aa1287
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 85 deletions.
4 changes: 2 additions & 2 deletions CefSharp.Core/Internals/ClientAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ namespace CefSharp

void ClientAdapter::OnRenderViewReady(CefRefPtr<CefBrowser> browser)
{
if (!Object::ReferenceEquals(_browserAdapter, nullptr) && !browser->IsPopup())
if (!Object::ReferenceEquals(_browserAdapter, nullptr) && !_browserAdapter->IsDisposed && !browser->IsPopup())
{
auto objectRepository = _browserAdapter->JavascriptObjectRepository;

Expand Down Expand Up @@ -1016,7 +1016,7 @@ namespace CefSharp

handled = true;
}
else if (name == kJavascriptAsyncMethodCallRequest)
else if (name == kJavascriptAsyncMethodCallRequest && !_browserAdapter->IsDisposed)
{
auto frameId = GetInt64(argList, 0);
auto objectId = GetInt64(argList, 1);
Expand Down
41 changes: 22 additions & 19 deletions CefSharp.Core/ManagedCefBrowserAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,34 @@ void ManagedCefBrowserAdapter::CreateOffscreenBrowser(IntPtr windowHandle, Brows

void ManagedCefBrowserAdapter::OnAfterBrowserCreated(int browserId)
{
//browser wrapper instance has to be set up for the BrowserProcessServiceHost
auto browser = _clientAdapter->GetCefBrowser();
if (browser != nullptr)
if (!_isDisposed)
{
//the js callback factory needs the browser instance to pass it to the js callback implementations for messaging purposes
auto cefSharpBrowserWrapper = gcnew CefSharpBrowserWrapper(browser);
_browserWrapper = cefSharpBrowserWrapper;
//browser wrapper instance has to be set up for the BrowserProcessServiceHost
auto browser = _clientAdapter->GetCefBrowser();
if (browser != nullptr)
{
//the js callback factory needs the browser instance to pass it to the js callback implementations for messaging purposes
_browserWrapper = gcnew CefSharpBrowserWrapper(browser);
}

_javascriptCallbackFactory->BrowserAdapter = gcnew WeakReference(this);
}

if (CefSharpSettings::WcfEnabled)
{
_browserProcessServiceHost = gcnew BrowserProcessServiceHost(_javaScriptObjectRepository, Process::GetCurrentProcess()->Id, this);
//NOTE: Attempt to solve timing issue where browser is opened and rapidly disposed. In some cases a call to Open throws
// an exception about the process already being closed. Two relevant issues are #862 and #804.
// Considering adding an IsDisposed check and also may have to revert to a try catch block
if (_browserProcessServiceHost->State == CommunicationState::Created)
if (CefSharpSettings::WcfEnabled)
{
_browserProcessServiceHost->Open();
_browserProcessServiceHost = gcnew BrowserProcessServiceHost(_javaScriptObjectRepository, Process::GetCurrentProcess()->Id, this);
//NOTE: Attempt to solve timing issue where browser is opened and rapidly disposed. In some cases a call to Open throws
// an exception about the process already being closed. Two relevant issues are #862 and #804.
// Considering adding an IsDisposed check and also may have to revert to a try catch block
if (_browserProcessServiceHost->State == CommunicationState::Created)
{
_browserProcessServiceHost->Open();
}
}
}

if (_webBrowserInternal != nullptr)
{
_webBrowserInternal->OnAfterBrowserCreated();
if (_webBrowserInternal != nullptr)
{
_webBrowserInternal->OnAfterBrowserCreated();
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion CefSharp.Core/ManagedCefBrowserAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ namespace CefSharp

~ManagedCefBrowserAdapter()
{
_isDisposed = true;
// Release the MCefRefPtr<ClientAdapter> reference
// before calling _browserWrapper->CloseBrowser(true)
this->!ManagedCefBrowserAdapter();

if (_browserWrapper != nullptr)
{
_browserWrapper->CloseBrowser(true);
Expand Down Expand Up @@ -109,7 +111,6 @@ namespace CefSharp

_webBrowserInternal = nullptr;
_javaScriptObjectRepository = nullptr;
_isDisposed = true;
}

virtual property bool IsDisposed
Expand Down
7 changes: 7 additions & 0 deletions CefSharp.Wpf.Example/CefSharp.Wpf.Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@
<Compile Include="Handlers\MenuHandler.cs" />
<Compile Include="Handlers\LifespanHandler.cs" />
<Compile Include="Handlers\PluginHandler.cs" />
<Compile Include="SpawnBrowsersWindow.xaml.cs">
<DependentUpon>SpawnBrowsersWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\BrowserTabView.xaml.cs">
<DependentUpon>BrowserTabView.xaml</DependentUpon>
</Compile>
Expand All @@ -144,6 +147,10 @@
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="SpawnBrowsersWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\BrowserTabView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
19 changes: 19 additions & 0 deletions CefSharp.Wpf.Example/SpawnBrowsersWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="CefSharp.Wpf.Example.SpawnBrowsersWindow"
Title="TestWindow" Height="594" Width="651">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="itemList" Margin="10,42,10,10" IsSynchronizedWithCurrentItem="False" SelectionChanged="ListBox_SelectionChanged" />
<ContentControl x:Name="browserContainer" Content="Browser goes here" Grid.Column="1" Margin="10,42,10,10"/>
<Button Content="Test" x:Name="btnTest" Height="27" Margin="10,10,10,0" VerticalAlignment="Top" Click="Button_Click"/>
<Label Content="Speed" Grid.Column="1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<Label x:Name="speedLabel" Content="0" Grid.Column="1" HorizontalAlignment="Left" Margin="300,10,0,0" VerticalAlignment="Top"/>
<Slider x:Name="speedSlider" Grid.Column="1" HorizontalAlignment="Left" Margin="58,15,0,0" VerticalAlignment="Top" Width="237" Maximum="1" Value="0.01" Minimum="0.01" ValueChanged="speedSlider_ValueChanged"/>

</Grid>
</Window>
89 changes: 89 additions & 0 deletions CefSharp.Wpf.Example/SpawnBrowsersWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace CefSharp.Wpf.Example
{
/// <summary>
/// Interaction logic for TestWindow.xaml
/// </summary>
public partial class SpawnBrowsersWindow : Window
{
bool _isRunning;
bool _requestCancel;
private const int MAX_SPEED = 1000;

public SpawnBrowsersWindow()
{
InitializeComponent();
for (int i = 1; i <= 100; i++)
{
itemList.Items.Add("Item " + i);
}
}

private async void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (browserContainer.Content is ChromiumWebBrowser)
{
ChromiumWebBrowser oldBrowser = browserContainer.Content as ChromiumWebBrowser;
browserContainer.Content = null;
oldBrowser.Dispose();
}
await Task.Delay(10);

ChromiumWebBrowser browser = new ChromiumWebBrowser()
{
Address = "http://www.google.com"
};
browserContainer.Content = browser;
//browser.ExecuteScriptAsync("document.body.innerHTML = '';");
}

private async void Button_Click(object sender, RoutedEventArgs e)
{
if (_isRunning)
{
StartStopTest(false);
}
else
{
StartStopTest(true);

for (int i = 0; i < itemList.Items.Count; i++)
{
itemList.SelectedIndex = i;
await Task.Delay((int)(MAX_SPEED * speedSlider.Value));
if (_requestCancel)
break;
}

StartStopTest(false);
}
}

private void StartStopTest(bool isStart)
{
_requestCancel = !isStart;
_isRunning = isStart;
btnTest.Content = isStart ? "Cancel" : "Test";
itemList.IsEnabled = !_isRunning;
}

private void speedSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
speedLabel.Content = string.Format("{0}ms", (int)(MAX_SPEED * speedSlider.Value));
}
}
}
Loading

0 comments on commit 7aa1287

Please sign in to comment.