Exemple #1
0
        static void P_ExecuteFullTaskWork <TResult>(TaskCompletionSource <IReadOnlyList <TResult> > proxy, IQueryExecutionJob <TResult> job, CancellationToken ct)
        {
            proxy.EnsureNotNull(nameof(proxy));
            job.EnsureNotNull(nameof(job));
            //
            try {
                var resultBuffer = new List <TResult>();
                Task <IQueryExecutionJobResult <TResult> > execAsync(IQueryExecutionJob <TResult> query)
                => (Task <IQueryExecutionJobResult <TResult> >)query.ExecuteAsync(cancellationToken: ct, taskCreationOptions: TaskCreationOptions.None).Task;

                void continuationWork(Task <IQueryExecutionJobResult <TResult> > locQueryExecTask, Action <Task <IQueryExecutionJobResult <TResult> > > locContinuationWorkRedirector)
                {
                    try {
                        if (locQueryExecTask.IsCanceled)
                        {
                            proxy.TrySetCanceled();
                            return;
                        }
                        else if (locQueryExecTask.IsFaulted)
                        {
                            proxy.TrySetException(exception: locQueryExecTask.Exception);
                            return;
                        }
                        IQueryExecutionJobResult <TResult> queryExecTaskResult;
                        try {
                            queryExecTaskResult = locQueryExecTask.Result;
                        }
                        catch (Exception exception) {
                            if (exception is OperationCanceledException)
                            {
                                proxy.TrySetCanceled();
                            }
                            else
                            {
                                proxy.TrySetException(exception);
                            }
                            return;
                        }
                        foreach (var queryResultElement in queryExecTaskResult.ResultData)
                        {
                            resultBuffer.Add(queryResultElement);
                        }
                        var continuationQuery = queryExecTaskResult.ContinuationQuery;
                        if (continuationQuery is null)
                        {
                            proxy.TrySetResult(result: new ListReadOnlyWrap <TResult>(list: resultBuffer));
                        }
                        else if (ct.IsCancellationRequested)
                        {
                            proxy.TrySetCanceled();
                        }
                        else
                        {
                            execAsync(continuationQuery)
                            .ContinueWith(
                                continuationAction: locContinuationWorkRedirector,
                                cancellationToken: ct,
                                continuationOptions: TaskContinuationOptions.PreferFairness | TaskContinuationOptions.AttachedToParent,
                                scheduler: TaskScheduler.Current ?? TaskScheduler.Default);
                        }
                    }
                    catch (Exception exception) {
                        proxy.TrySetException(exception);
                    }
                }
                void continuationWorkRedirector(Task <IQueryExecutionJobResult <TResult> > locTsk)
                => continuationWork(locQueryExecTask: locTsk, locContinuationWorkRedirector: (global::System.Action <global::System.Threading.Tasks.Task <global::Eon.Linq.IQueryExecutionJobResult <TResult> > >)continuationWorkRedirector);

                execAsync(query: job)
                .ContinueWith(
                    continuationAction: locTsk => continuationWork(locQueryExecTask: locTsk, locContinuationWorkRedirector: (global::System.Action <global::System.Threading.Tasks.Task <global::Eon.Linq.IQueryExecutionJobResult <TResult> > >)continuationWorkRedirector),
                    cancellationToken: ct,
                    continuationOptions: TaskContinuationOptions.PreferFairness | TaskContinuationOptions.AttachedToParent,
                    scheduler: TaskScheduler.Current ?? TaskScheduler.Default);
            }
            catch (Exception exception) {
                proxy.TrySetException(exception);
            }
        }
Exemple #2
0
            // TODO: Put strings into the resources.
            //
            static void P_ProvideResult(P_SessionObject session, TaskCompletionSource <TResult> resultConsumer, IContext ctx = default)
            {
                session.EnsureNotNull(nameof(session));
                resultConsumer.EnsureNotNull(nameof(resultConsumer));
                //
                var unhandledExceptionObserver = session.P_UnhandledExceptionObserver;
                var ct             = ctx.Ct();
                var ctRegistration = default(CancellationTokenRegistration?);

                resultConsumer.Task.ContinueWith(continuationAction: locTask => itrlck.Or(ref session._executionStateFlag, __ExecutionStateFlag_Completed), continuationOptions: TaskContinuationOptions.ExecuteSynchronously);
                resultConsumer.Task.ContinueWith(continuationAction: locTask => ctRegistration?.Dispose(), continuationOptions: TaskContinuationOptions.PreferFairness);
                //
                var previousExecutionStateFlag = itrlck.Or(location: ref session._executionStateFlag, value: __ExecutionStateFlag_AboutExecution);

                if (previousExecutionStateFlag == __ExecutionStateFlag_None)
                {
                    // Флаг отмены до начала выполнения не был установлен.
                    //
                    if (ct.IsCancellationRequested)
                    {
                        if (session.P_TrySetResultAsCanceled(ct))
                        {
                            resultConsumer.TrySetCanceled();
                        }
                    }
                    else
                    {
                        if (ct.CanBeCanceled)
                        {
                            ctRegistration = ct.Register(callback: () => { if (session.P_TrySetResultAsCanceled(ct))
                                                                           {
                                                                               resultConsumer.TrySetCanceled();
                                                                           }
                                                         });
                        }
                        //
                        var factoryTask =
                            Task
                            .Factory
                            .StartNew(
                                function:
                                () => {
                            // Собственно, здесь выполняется делегат операции, указанный одним из конструкторов AsyncOperator`1.
                            //
                            var locFactoryTask = session.P_Factory(arg: ctx);
                            if (locFactoryTask is null)
                            {
                                throw
                                new EonException(message: $"Factory method has returned invalid result '{FormatStringUtilitiesCoreL0.GetNullValueText()}'.{Environment.NewLine}\tMethod:{session.P_Factory.FmtStr().GNLI2()}");
                            }
                            return(locFactoryTask);
                        },
                                cancellationToken: ct,
                                creationOptions: TaskCreationOptions.PreferFairness,
                                scheduler: TaskScheduler.Default)
                            .Unwrap();
                        var factoryTaskResultHandlingTask =
                            factoryTask
                            .ContinueWith(
                                continuationAction:
                                locTask => {
                            if (locTask.IsCanceled)
                            {
                                if (session.P_TrySetResultAsCanceled(ct: CancellationToken.None))
                                {
                                    resultConsumer.TrySetCanceled(cancellationToken: CancellationToken.None);
                                }
                            }
                            else if (locTask.IsFaulted)
                            {
                                var locTaskException = locTask.Exception.Flatten();
                                try {
                                    if (session.P_TrySetResultAsFaulted(locTaskException))
                                    {
                                        resultConsumer.TrySetException(locTaskException);
                                        return;
                                    }
                                }
                                catch (Exception locException) {
                                    throw new AggregateException(locTaskException, locException);
                                }
                                throw new AggregateException(locTaskException);
                            }
                            else if (session.P_TrySetOrDisposeResult(locTask.Result))
                            {
                                resultConsumer.TrySetResult(locTask.Result);
                            }
                        },
                                cancellationToken: CancellationToken.None,
                                continuationOptions: TaskContinuationOptions.PreferFairness,
                                scheduler: TaskScheduler.Default);
                        if (!(unhandledExceptionObserver is null || ReferenceEquals(objA: unhandledExceptionObserver, objB: NopUnhandledExceptionObserver.Instance)))
                        {
                            factoryTaskResultHandlingTask
                            .ContinueWith(
                                continuationAction:
                                locTask => {
                                var locTaskException = locTask.Exception.Flatten();
                                try {
                                    if (unhandledExceptionObserver.ObserveException(exception: locTaskException, component: session, message: $"An exception was thrown by async operator ({nameof(AsyncOperator<TResult>)}) session.", exceptionCtx: ctx))
                                    {
                                        return;
                                    }
                                }
                                catch (Exception locException) {
                                    throw new AggregateException(locTaskException, locException);
                                }
                                throw new AggregateException(locTaskException);
                            },
                                continuationOptions: TaskContinuationOptions.OnlyOnFaulted,
                                cancellationToken: default,