Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 71 additions & 53 deletions CefSharp.WinForms/ChromiumWebBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.ComponentModel;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Forms;
using CefSharp.Internals;
using CefSharp.WinForms.Internals;
Expand Down Expand Up @@ -59,6 +60,25 @@ public class ChromiumWebBrowser : Control, IWebBrowserInternal, IWinFormsWebBrow
/// </summary>
private IRequestContext requestContext;

/// <summary>
/// The value for disposal, if it's 1 (one) then this instance is either disposed
/// or in the process of getting disposed
/// </summary>
private int disposeSignaled;

/// <summary>
/// Gets a value indicating whether this instance is disposed.
/// </summary>
/// <value><see langword="true" /> if this instance is disposed; otherwise, <see langword="false" />.</value>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DefaultValue(false)]
public new bool IsDisposed
{
get
{
return Interlocked.CompareExchange(ref disposeSignaled, 1, 1) == 1;
}
}

/// <summary>
/// Set to true while handing an activating WM_ACTIVATE message.
/// MUST ONLY be cleared by DefaultFocusHandler.
Expand Down Expand Up @@ -431,79 +451,77 @@ private void InitializeFieldsAndCefIfRequired()
}

/// <summary>
/// Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.Control" /> and its child controls and optionally releases the managed resources.
/// If not in design mode; Releases unmanaged and - optionally - managed resources for the <see cref="ChromiumWebBrowser"/>
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
/// <param name="disposing"><see langword="true" /> to release both managed and unmanaged resources; <see langword="false" /> to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
IsBrowserInitialized = false;

if (!designMode)
// Attempt to move the disposeSignaled state from 0 to 1. If successful, we can be assured that
// this thread is the first thread to do so, and can safely dispose of the object.
if (Interlocked.CompareExchange(ref disposeSignaled, 1, 0) != 0)
{
RemoveFromListOfCefBrowsers();
return;
}

//The unmanaged resources should never be created in design mode, so only dispose when
//at runtime
if (disposing && !designMode)
if (!designMode)
{
FreeUnmanagedResources();
InternalDispose(disposing);
}

// Don't maintain a reference to event listeners anylonger:
AddressChanged = null;
ConsoleMessage = null;
FrameLoadEnd = null;
FrameLoadStart = null;
IsBrowserInitializedChanged = null;
LoadError = null;
LoadingStateChanged = null;
StatusMessage = null;
TitleChanged = null;

// Release reference to handlers, make sure this is done after we dispose managedCefBrowserAdapter
// otherwise the ILifeSpanHandler.DoClose will not be invoked.
this.SetHandlersToNull();

base.Dispose(disposing);
}

/// <summary>
/// Required for designer support - this method cannot be inlined as the designer
/// will attempt to load libcef.dll and will subsiquently throw an exception.
/// Releases unmanaged and - optionally - managed resources for the <see cref="ChromiumWebBrowser"/>
/// </summary>
/// <param name="disposing"><see langword="true" /> to release both managed and unmanaged resources; <see langword="false" /> to release only unmanaged resources.</param>
/// <remarks>
/// This method cannot be inlined as the designer will attempt to load libcef.dll and will subsiquently throw an exception.
/// </remarks>
[MethodImpl(MethodImplOptions.NoInlining)]
private void RemoveFromListOfCefBrowsers()
private void InternalDispose(bool disposing)
{
Cef.RemoveDisposable(this);
}
if (disposing)
{
IsBrowserInitialized = false;

/// <summary>
/// Required for designer support - this method cannot be inlined as the designer
/// will attempt to load libcef.dll and will subsiquently throw an exception.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private void FreeUnmanagedResources()
{
browser = null;
browser = null;

if (parentFormMessageInterceptor != null)
{
parentFormMessageInterceptor.Dispose();
parentFormMessageInterceptor = null;
}
if (parentFormMessageInterceptor != null)
{
parentFormMessageInterceptor.Dispose();
parentFormMessageInterceptor = null;
}

if (browserSettings != null)
{
browserSettings.Dispose();
browserSettings = null;
}
if (browserSettings != null)
{
browserSettings.Dispose();
browserSettings = null;
}

if (managedCefBrowserAdapter != null)
{
managedCefBrowserAdapter.Dispose();
managedCefBrowserAdapter = null;
if (managedCefBrowserAdapter != null)
{
managedCefBrowserAdapter.Dispose();
managedCefBrowserAdapter = null;
}

// Don't maintain a reference to event listeners anylonger:
AddressChanged = null;
ConsoleMessage = null;
FrameLoadEnd = null;
FrameLoadStart = null;
IsBrowserInitializedChanged = null;
LoadError = null;
LoadingStateChanged = null;
StatusMessage = null;
TitleChanged = null;

// Release reference to handlers, make sure this is done after we dispose managedCefBrowserAdapter
// otherwise the ILifeSpanHandler.DoClose will not be invoked.
this.SetHandlersToNull();
}

Cef.RemoveDisposable(this);
}

/// <summary>
Expand Down Expand Up @@ -643,7 +661,7 @@ private void CreateBrowser()
{
var windowInfo = new WindowInfo();
windowInfo.SetAsChild(Handle);

managedCefBrowserAdapter.CreateBrowser(windowInfo, browserSettings as BrowserSettings, requestContext as RequestContext, Address);

if (browserSettings != null)
Expand Down
Loading