private void Dispose(bool isDisposing = true) { if (isDisposing) { lock (SyncRoot) { if (this.isDisposing) { return; } this.isDisposing = true; } GC.SuppressFinalize(this); } var disposed = false; void InternalDispose() { if (disposed) { return; // bail-out } disposed = true; AsyncCancellationTokenSource?.Cancel(); WebViewInitialized = null; BeforeNavigate = null; BeforeResourceLoad = null; Navigated = null; LoadFailed = null; DownloadProgressChanged = null; DownloadCompleted = null; DownloadCancelled = null; JavascriptContextCreated = null; TitleChanged = null; UnhandledAsyncException = null; JavascriptContextReleased = null; foreach (var disposable in disposables.Concat(JsExecutors?.Values)) { disposable?.Dispose(); } Disposed?.Invoke(); } if (JavascriptPendingCalls?.CurrentCount > 1) { // avoid dead-lock, wait for all pending calls to finish Task.Run(() => { JavascriptPendingCalls?.Signal(); // remove dummy entry JavascriptPendingCalls?.Wait(); InternalDispose(); }); return; } InternalDispose(); }
public void Dispose() { lock (SyncRoot) { if (isDisposing) { return; } isDisposing = true; } GC.SuppressFinalize(this); var disposed = false; void InternalDispose() { if (disposed) { return; // bail-out } disposed = true; AsyncCancellationTokenSource.Cancel(); WebViewInitialized = null; BeforeNavigate = null; BeforeResourceLoad = null; Navigated = null; LoadFailed = null; DownloadProgressChanged = null; DownloadCompleted = null; DownloadCancelled = null; JavascriptContextCreated = null; TitleChanged = null; UnhandledAsyncException = null; RenderProcessCrashed = null; JavascriptContextReleased = null; try { foreach (var jsExecutor in JsExecutors.Values) { jsExecutor.Dispose(); } } catch (Exception e) { throw new Exception("Exception ocurred while disposing " + nameof(JsExecutors), e); } if (disposables != null) { foreach (var disposable in disposables) { disposable.Dispose(); } } Disposed?.Invoke(); } // avoid dead-lock, wait for all pending calls to finish JavascriptCallFinished += () => { if (javascriptPendingCalls == 0) { Dispatcher.BeginInvoke((Action)InternalDispose); } }; if (javascriptPendingCalls > 0) { // JavascriptCallFinished event will trigger InternalDispose, // this check must come after registering event to avoid losing the event call return; } InternalDispose(); }
private void InnerDispose() { lock (SyncRoot) { if (isDisposing) { return; } isDisposing = true; } var disposed = false; void InternalDispose() { if (disposed) { return; // bail-out } disposed = true; AsyncCancellationTokenSource?.Cancel(); chromium.JavascriptContextCreated -= OnJavascriptContextCreated; chromium.JavascriptContextReleased -= OnJavascriptContextReleased; WebViewInitialized = null; BeforeNavigate = null; BeforeResourceLoad = null; Navigated = null; LoadFailed = null; DownloadProgressChanged = null; DownloadCompleted = null; DownloadCancelled = null; JavascriptContextCreated = null; TitleChanged = null; UnhandledAsyncException = null; JavascriptContextReleased = null; // dispose the js executors before the browser to prevent (the browser) from throwing cancellation exceptions DisposeJavascriptExecutors(); foreach (var disposable in disposables) { disposable?.Dispose(); } Disposed?.Invoke(); } if (JavascriptPendingCalls?.CurrentCount > 1) { // avoid dead-lock, wait for all pending calls to finish Task.Run(() => { JavascriptPendingCalls?.Signal(); // remove dummy entry JavascriptPendingCalls?.Wait(); InternalDispose(); }); return; } InternalDispose(); }