protected override async Task <DependencyResult <TDependencyInstance> > ResolveDependencyAsync(IDependencyResolutionContext ctx) { var specs = ctx.EnsureNotNull(nameof(ctx)).Value.Specs; // if (specs.DependencyType.IsAssignableFrom(DependencyInstanceType)) { var newInstanceResult = default(DependencyResult <TDependencyInstance>); if (specs.IsNewInstanceRequired || !CanShareDependency) { try { newInstanceResult = await ResolveNewDependencyInstanceAsync(ctx : ctx).ConfigureAwait(false); if (newInstanceResult.Instance is null) { return(newInstanceResult); } else if (!newInstanceResult.IsNewInstance) { throw new EonException( message: $"Результат вызова метода '{nameof(ResolveNewDependencyInstanceAsync)}' не соответствует ожидаемому. В частности, свойство результата '{nameof(newInstanceResult)}.{nameof(newInstanceResult.IsNewInstance)}' не соответствует ожидаемому значение '{bool.TrueString}'."); } else if (specs.PreventNewInstanceInitialization) { return(newInstanceResult); } else { await P_InitializeNewDependencyInstanceAsync(instance : newInstanceResult.Instance).ConfigureAwait(false); return(newInstanceResult); } } catch (Exception exception) { if (newInstanceResult.IsNewInstance) { (newInstanceResult.Instance as IDisposable)?.Dispose(exception); } throw; } } else { // В спецификации запроса отсутствует требование разрешения зависимости именно в новый экземпляр (см. specs.IsNewInstanceRequired) + обработчик может "шарить" экземпляр (см. CanShareDependency). // var sharedInstanceStore = ReadDA(ref _sharedInstanceStore); if (sharedInstanceStore is null) { var lck = ReadDA(ref _sharedInstanceInitializationLock); var lckAcquired = false; try { lckAcquired = await lck.WaitAsync(millisecondsTimeout : TaskUtilities.DefaultAsyncTimeoutMilliseconds).ConfigureAwait(false); if (!lckAcquired) { throw new LockAcquisitionFailException(reason: LockAcquisitionFailReason.TimeoutElapsed); } // sharedInstanceStore = ReadDA(ref _sharedInstanceStore); if (sharedInstanceStore is null) { try { newInstanceResult = await ResolveNewDependencyInstanceAsync(ctx : ctx).ConfigureAwait(false); if (newInstanceResult.Instance is null) { WriteDA(location: ref _sharedInstanceStore, value: sharedInstanceStore = default(TDependencyInstance).ToValueHolder(ownsValue: false)); } else if (!newInstanceResult.IsNewInstance) { throw new EonException( message: $"Результат вызова метода '{nameof(ResolveNewDependencyInstanceAsync)}' не соответствует ожидаемому. В частности, свойство результата '{nameof(newInstanceResult)}.{nameof(newInstanceResult.IsNewInstance)}' не соответствует ожидаемому значение '{bool.TrueString}'."); } else if (specs.PreventNewInstanceInitialization) { WriteDA( location: ref _sharedInstanceStore, value: sharedInstanceStore = newInstanceResult.Instance.ToValueHolder(ownsValue: true)); } else { try { await P_InitializeNewDependencyInstanceAsync(instance : newInstanceResult.Instance).ConfigureAwait(false); sharedInstanceStore = newInstanceResult.Instance.ToValueHolder(ownsValue: true); } catch (Exception exception) { sharedInstanceStore = new Vh <TDependencyInstance>(exception: exception); } WriteDA(location: ref _sharedInstanceStore, value: sharedInstanceStore); } } catch (Exception exception) { if (newInstanceResult.IsNewInstance && !ReferenceEquals(itrlck.Get(ref _sharedInstanceStore)?.ValueDisposeTolerant, newInstanceResult.Instance)) { (newInstanceResult.Instance as IDisposable)?.Dispose(exception); } throw; } } } finally { if (lckAcquired) { try { lck.Release(); } catch (ObjectDisposedException) { } } } } if (sharedInstanceStore.Value is null) { return(DependencyResult <TDependencyInstance> .None); } else { return(new DependencyResult <TDependencyInstance>(instance: sharedInstanceStore.Value, isNewInstance: false)); } } } else { return(DependencyResult <TDependencyInstance> .None); } }
static void P_Loop(object state) { var startState = state.EnsureNotNull(nameof(state)).EnsureOfType <P_LoopStartState>().Value; // var ctx = startState.Context; IUnhandledExceptionObserver unhandledExceptionObserver; IRunControl runControl; CancellationToken ct; Func <CancellationToken, IVh <TCtxState> > stateFactory; ManualResetEventSlim awakeLoopEvent; Queue <P_InvokeItemBase> queue; PrimitiveSpinLock queueSpinLock; try { unhandledExceptionObserver = ctx.P_UnhandledExceptionObserver; runControl = ctx.RunControl; ct = ctx.P_Ct; stateFactory = ctx.P_StateFactory; awakeLoopEvent = ctx.P_AwakeLoopEvent; queue = ctx.P_InvokeQueue; queueSpinLock = ctx.P_InvokeQueueSpinLock; } catch (ObjectDisposedException) { return; } var bypassUnhandledExceptionObserver = false; try { Exception caughtException1 = default; try { ctx.P_IsLoopAlive = true; startState.LoopStartedEvent.Set(); // IVh <TCtxState> ctxState = default; Exception caughtException2 = default; try { // Создание объекта состояния контекста. // try { ctxState = stateFactory(arg: ct); } catch (Exception exception) { ctxState = new Vh <TCtxState>(exception: exception); } // Цикл обработки очереди. // for (; ;) { if (runControl.HasStopRequested || ct.IsCancellationRequested) { break; } // P_InvokeItemBase queueItem = default; try { queueItem = queueSpinLock.Invoke(() => queue.Count > 0 ? queue.Dequeue() : null); if (!(queueItem is null)) { if (queueItem.IsInvokeCompleted) { continue; } else { try { itrlck.Set(ref ctx._currentInvoke, queueItem); queueItem.Invoke(ctx: ctx, ctxState: ctxState); } catch (Exception exception) { if (bypassUnhandledExceptionObserver) { throw; } else { bool isExceptionObserved; try { isExceptionObserved = unhandledExceptionObserver.ObserveException(exception: exception, component: queueItem); } catch (Exception secondException) { bypassUnhandledExceptionObserver = true; throw new AggregateException(exception, secondException); } if (!isExceptionObserved) { bypassUnhandledExceptionObserver = true; throw; } } } } finally { itrlck.SetNull(ref ctx._currentInvoke, queueItem); } continue; } } catch (Exception exception) { try { queueItem.TrySetInvokeResultAsCanceled(); } catch (Exception secondException) { throw new AggregateException(exception, secondException); } throw; } // Ожидание. // if (awakeLoopEvent.IsSet) { awakeLoopEvent.Reset(); } else { awakeLoopEvent.Wait(millisecondsTimeout: 937); } } } catch (Exception exception) { caughtException2 = exception; throw; } finally { ctxState?.Dispose(exception: caughtException2); } }