public async Task <ShellScope> GetScopeAsync(ShellSettings settings) { ShellScope scope = null; ShellContext shellContext = null; while (scope == null) { if (!_shellContexts.TryGetValue(settings.Name, out shellContext)) { shellContext = await GetOrCreateShellContextAsync(settings); } // We create a scope before checking if the shell has been released. scope = shellContext.CreateScope(); // If CreateScope() returned null, the shell is released. We then remove it and // retry with the hope to get one that won't be released before we create a scope. if (scope == null) { // If the context is released, it is removed from the dictionary so that // a new call on 'GetScope' will recreate a new shell context. _shellContexts.TryRemove(settings.Name, out var value); } } return(scope); }
/// <summary> /// Activate the shell, if not yet done, by calling the related tenant event handlers. /// </summary> public async Task ActivateShellAsync() { if (ShellContext.IsActivated) { return; } SemaphoreSlim semaphore; lock (_semaphores) { if (!_semaphores.TryGetValue(ShellContext.Settings.Name, out semaphore)) { _semaphores[ShellContext.Settings.Name] = semaphore = new SemaphoreSlim(1); } } await semaphore.WaitAsync(); try { // The tenant gets activated here. if (!ShellContext.IsActivated) { using (var scope = ShellContext.CreateScope()) { if (scope == null) { return; } scope.StartAsyncFlow(); var tenantEvents = scope.ServiceProvider.GetServices <IModularTenantEvents>(); foreach (var tenantEvent in tenantEvents) { await tenantEvent.ActivatingAsync(); } foreach (var tenantEvent in tenantEvents.Reverse()) { await tenantEvent.ActivatedAsync(); } await scope.BeforeDisposeAsync(); await scope.DisposeAsync(); } ShellContext.IsActivated = true; } } finally { semaphore.Release(); } }