/// <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); } }
/// <summary> /// Perform Cmdlet post-processing. /// </summary> protected sealed override void EndProcessing() { ThreadAffinitiveSynchronizationContext.RunSynchronized( () => EndProcessingAsync() ); }
/// <summary> /// Perform Cmdlet processing. /// </summary> protected sealed override void ProcessRecord() { ThreadAffinitiveSynchronizationContext.RunSynchronized( () => ProcessRecordAsync() ); }