/// <summary> /// Terminate the shell, if released and in its last scope, by calling the related event handlers. /// Returns true if the shell context should be disposed consequently to this scope being released. /// </summary> private async Task <bool> TerminateShellAsync() { // A disabled shell still in use is released by its last scope. if (ShellContext.Settings.State == TenantState.Disabled) { if (Interlocked.CompareExchange(ref ShellContext._refCount, 1, 1) == 1) { ShellContext.Release(); } } // If the context is still being released, it will be disposed if the ref counter is equal to 0. // To prevent this while executing the terminating events, the ref counter is not decremented here. if (ShellContext._released && Interlocked.CompareExchange(ref ShellContext._refCount, 1, 1) == 1) { var tenantEvents = _serviceScope.ServiceProvider.GetServices <IModularTenantEvents>(); foreach (var tenantEvent in tenantEvents) { await tenantEvent.TerminatingAsync(); } foreach (var tenantEvent in tenantEvents.Reverse()) { await tenantEvent.TerminatedAsync(); } return(true); } return(false); }