コード例 #1
0
        public static bool TryGetContext <TCmdlet>(
            TCmdlet cmdlet,
            [MaybeNullWhen(false)]
            out AsyncCmdletContext context)
            where TCmdlet :
        Cmdlet,
        IAsyncCmdlet
        {
            Requires.NotNull(cmdlet, nameof(cmdlet));

            context = null !;

            if (!_contexts.TryGetValue(cmdlet, out var ctx))
            {
                return(false);
            }

            if (ctx._disposed)
            {
                return(false);
            }

            context = ctx;
            return(true);
        }
コード例 #2
0
        public static AsyncCmdletContext Start <TCmdlet>(
            TCmdlet cmdlet)
            where TCmdlet :
        Cmdlet,
        IAsyncCmdlet
        {
            Requires.NotNull(cmdlet, nameof(cmdlet));

            var context = new AsyncCmdletContext(cmdlet);

            return(context);
        }
コード例 #3
0
        public static void CancelAsyncOperations <TCmdlet>(
            this TCmdlet cmdlet)
            where TCmdlet :
        Cmdlet,
        IAsyncCmdlet
        {
            Requires.NotNull(cmdlet, nameof(cmdlet));

            if (AsyncCmdletContext.TryGetContext(cmdlet, out var context))
            {
                context.CancelAsyncOperations();
            }
        }
コード例 #4
0
        internal static Task <TResult> QueueAction <TCmdlet, TArgument, TResult>(
            this TCmdlet cmdlet,
            Func <TCmdlet, TArgument, AsyncCmdletContext, TResult> action,
            TArgument argument,
            bool runSynchronouslyIfOnTheMainThread,
            CancellationToken cancellationToken)
            where TCmdlet :
        Cmdlet,
        IAsyncCmdlet
        {
            Requires.NotNull(cmdlet, nameof(cmdlet));
            Requires.NotNull(action, nameof(action));

            var context = AsyncCmdletContext.GetContext(cmdlet);

            var task = context.QueueAction(
                cmdlet,
                action,
                argument,
                runSynchronouslyIfOnTheMainThread,
                cancellationToken);

            return(task);
        }
コード例 #5
0
        public static void RunAsyncPipeline <TCmdlet>(
            TCmdlet cmdlet,
            Func <TCmdlet, CancellationToken, Task> asyncMethod,
            string pipelineStage)
            where TCmdlet :
        Cmdlet,
        IAsyncCmdlet
        {
            using var diagnosticSource = new SwitchingDiagnosticSource(
                      DiagnosticConstants.SourceName,
                      DiagnosticConstants.TraceSwitchName);

            using var pipelineStageActivity = ActivityScope.Start(
                      diagnosticSource,
                      new Activity(
                          DiagnosticConstants.AsyncPipelineStageActivity),
                      new
            {
                StageName = pipelineStage
            });

            using var context = AsyncCmdletContext.Start(cmdlet);

            var asyncTask = asyncMethod(cmdlet, context.GetCancellationToken());

            if (asyncTask is null)
            {
                throw new InvalidOperationException();
            }

            ExceptionDispatchInfo?exceptionDispatcher = null;

            try
            {
                asyncTask.ContinueWith(
                    (t, state) =>
                    ((AsyncCmdletContext?)state) !.Close(),
                    context,
                    CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously,
                    TaskScheduler.Current);

                foreach (var action in context.GetActions())
                {
                    using var pipelineStepActivity = ActivityScope.Start(
                              diagnosticSource,
                              new Activity(
                                  DiagnosticConstants.AsyncPipelineStepActivity));

                    action.Invoke();
                }
            }
            finally
            {
                try
                {
                    asyncTask.GetAwaiter().GetResult();
                }
                catch (OperationCanceledException)
                {
                }
                catch (AggregateException ex)
                {
                    var exceptions = ex.Flatten().InnerExceptions;

                    var pse = exceptions.FirstOrDefault(e => e is PipelineStoppedException);

                    if (pse != null)
                    {
                        exceptionDispatcher = ExceptionDispatchInfo.Capture(pse);
                    }
                    else if (exceptions.Any(e => !(e is OperationCanceledException)))
                    {
                        exceptionDispatcher = ExceptionDispatchInfo.Capture(ex);
                    }
                }
            }

            exceptionDispatcher?.Throw();
        }