Example #1
0
        /// <summary>
        ///     Run an asynchronous operation using the current thread as its synchronisation context.
        /// </summary>
        /// <param name="asyncOperation">
        ///     A <see cref="Func{TResult}"/> delegate representing the asynchronous operation to run.
        /// </param>
        public static void RunSynchronized(Func <Task> asyncOperation)
        {
            if (asyncOperation == null)
            {
                throw new ArgumentNullException(nameof(asyncOperation));
            }

            SynchronizationContext savedContext = Current;

            try
            {
                using (ThreadAffinitiveSynchronizationContext synchronizationContext = new ThreadAffinitiveSynchronizationContext())
                {
                    SetSynchronizationContext(synchronizationContext);

                    Task rootOperationTask = asyncOperation();
                    if (rootOperationTask == null)
                    {
                        throw new InvalidOperationException("The asynchronous operation delegate cannot return null.");
                    }

                    rootOperationTask.ContinueWith(
                        operationTask =>
                        synchronizationContext.TerminateMessagePump(),
                        scheduler:
                        TaskScheduler.Default
                        );

                    synchronizationContext.RunMessagePump();

                    try
                    {
                        rootOperationTask
                        .GetAwaiter()
                        .GetResult();
                    }
                    catch (AggregateException eWaitForTask) // The TPL will almost always wrap an AggregateException around any exception thrown by the async operation.
                    {
                        // Is this just a wrapped exception?
                        AggregateException flattenedAggregate = eWaitForTask.Flatten();
                        if (flattenedAggregate.InnerExceptions.Count != 1)
                        {
                            throw; // Nope, genuine aggregate.
                        }
                        // Yep, so rethrow (preserving original stack-trace).
                        ExceptionDispatchInfo
                        .Capture(
                            flattenedAggregate
                            .InnerExceptions[0]
                            )
                        .Throw();
                    }
                }
            }
            finally
            {
                SetSynchronizationContext(savedContext);
            }
        }
Example #2
0
 /// <summary>
 ///     Perform Cmdlet post-processing.
 /// </summary>
 protected sealed override void EndProcessing()
 {
     ThreadAffinitiveSynchronizationContext.RunSynchronized(
         () => EndProcessingAsync()
         );
 }
Example #3
0
 /// <summary>
 ///     Perform Cmdlet processing.
 /// </summary>
 protected sealed override void ProcessRecord()
 {
     ThreadAffinitiveSynchronizationContext.RunSynchronized(
         () => ProcessRecordAsync()
         );
 }