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

            var savedContext = Current;

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

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

                    rootOperationTask.ContinueWith(
                        operationTask =>
                        // ReSharper disable once AccessToDisposedClosure
                        synchronizationContext.TerminateMessagePump(),
                        TaskScheduler.Default
                        );

                    synchronizationContext.RunMessagePump();

                    try{
                        return
                            (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?
                        var 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();

                        throw; // Never reached.
                    }
                }
            }
            finally{
                SetSynchronizationContext(savedContext);
            }
        }
예제 #2
0
 /// <summary>
 ///     Perform Cmdlet post-processing.
 /// </summary>
 protected sealed override void EndProcessing()
 {
     ThreadAffinitiveSynchronizationContext.RunSynchronized(EndProcessingAsync);
 }
예제 #3
0
 /// <summary>
 ///     Perform Cmdlet processing.
 /// </summary>
 protected sealed override void ProcessRecord()
 {
     ThreadAffinitiveSynchronizationContext.RunSynchronized(ProcessRecordAsync);
 }