int IVsShellPropertyEvents.OnShellPropertyChange(int propid, object var) { if (propid == (int)__VSSPROPID.VSSPROPID_Zombie || propid == (int)__VSSPROPID4.VSSPROPID_ShellInitialized) { if (!(bool)var) { ShellAvailable?.Invoke(); } } else if (propid == (int)__VSSPROPID6.VSSPROPID_ShutdownStarted) { if (!(bool)var) { ShutdownStarted?.Invoke(); } } else if (propid == (int)__VSSPROPID2.VSSPROPID_MainWindowVisibility) { // TODO: Test to see if 'var' is a bool. It may be an int if (var is bool isVisible) { MainWindowVisibilityChanged?.Invoke(isVisible); } } return(VSConstants.S_OK); }
/// <summary> /// Begins the process of shutting down the dispatcher, synchronously. /// The process may complete asynchronously, since we may be /// nested in dispatcher frames. /// </summary> public void InvokeShutdown() { VerifyAccess(); if (this._hasShutdownFinished) { throw new InvalidOperationException(); } try { if (!this._hasShutdownStarted) { // Call the ShutdownStarted event before we actually mark ourselves // as shutting down. This is so the handlers can actaully do work // when they get this event without throwing exceptions. ShutdownStarted?.Invoke(this, EventArgs.Empty); this._hasShutdownStarted = true; if (this._frameDepth > 0) { // If there are any frames running, we have to wait for them // to unwind before we can safely destroy the dispatcher. } else { // The current thread is not spinning inside of the Dispatcher, // so we can go ahead and destroy it. ShutdownImpl(); } _dispatchers.Remove(this._thread.ManagedThreadId); } } catch (Exception e) { if (this._finalExceptionHandler == null || !this._finalExceptionHandler(this, e)) { throw; } } }