<PackageReference Include="NUnit" Version="3.11.0" />

MessagePumpStrategy

abstract class MessagePumpStrategy
using System; using System.Security; using System.Threading; using System.Windows.Forms; using System.Windows.Threading; namespace NUnit.Framework.Internal { internal abstract class MessagePumpStrategy { private sealed class NoMessagePumpStrategy : MessagePumpStrategy { public static readonly NoMessagePumpStrategy Instance = new NoMessagePumpStrategy(); private NoMessagePumpStrategy() { } public override void WaitForCompletion(AwaitAdapter awaitable) { awaitable.BlockUntilCompleted(); } } private sealed class WindowsFormsMessagePumpStrategy : MessagePumpStrategy { public static readonly WindowsFormsMessagePumpStrategy Instance = new WindowsFormsMessagePumpStrategy(); private WindowsFormsMessagePumpStrategy() { } [SecuritySafeCritical] public override void WaitForCompletion(AwaitAdapter awaitable) { SynchronizationContext current = SynchronizationContext.Current; if (!(current is WindowsFormsSynchronizationContext)) throw new InvalidOperationException("This strategy must only be used from a WindowsFormsSynchronizationContext."); if (!awaitable.IsCompleted) { current.Post(delegate(object state) { ContinueOnSameSynchronizationContext((AwaitAdapter)state, (Action)Application.Exit); }, awaitable); try { Application.Run(); } finally { SynchronizationContext.SetSynchronizationContext(current); } } } } private sealed class WpfMessagePumpStrategy : MessagePumpStrategy { public static readonly WpfMessagePumpStrategy Instance = new WpfMessagePumpStrategy(); private WpfMessagePumpStrategy() { } public override void WaitForCompletion(AwaitAdapter awaitable) { SynchronizationContext current = SynchronizationContext.Current; if (!(current is DispatcherSynchronizationContext)) throw new InvalidOperationException("This strategy must only be used from a DispatcherSynchronizationContext."); if (!awaitable.IsCompleted) { current.Post(delegate(object state) { ContinueOnSameSynchronizationContext((AwaitAdapter)state, (Action)Dispatcher.ExitAllFrames); }, awaitable); Dispatcher.Run(); } } } private sealed class SingleThreadedTestMessagePumpStrategy : MessagePumpStrategy { public static readonly SingleThreadedTestMessagePumpStrategy Instance = new SingleThreadedTestMessagePumpStrategy(); private SingleThreadedTestMessagePumpStrategy() { } public override void WaitForCompletion(AwaitAdapter awaitable) { SingleThreadedTestSynchronizationContext context = SynchronizationContext.Current as SingleThreadedTestSynchronizationContext; if (context == null) throw new InvalidOperationException("This strategy must only be used from a SingleThreadedTestSynchronizationContext."); if (!awaitable.IsCompleted) { context.Post(delegate(object state) { ContinueOnSameSynchronizationContext((AwaitAdapter)state, context.ShutDown); }, awaitable); context.Run(); } } } public abstract void WaitForCompletion(AwaitAdapter awaitable); public static MessagePumpStrategy FromCurrentSynchronizationContext() { SynchronizationContext current = SynchronizationContext.Current; if (current is SingleThreadedTestSynchronizationContext) return SingleThreadedTestMessagePumpStrategy.Instance; if (current is WindowsFormsSynchronizationContext) return WindowsFormsMessagePumpStrategy.Instance; if (current is DispatcherSynchronizationContext) return WpfMessagePumpStrategy.Instance; return NoMessagePumpStrategy.Instance; } private static void ContinueOnSameSynchronizationContext(AwaitAdapter adapter, Action continuation) { if (adapter == null) throw new ArgumentNullException("adapter"); if (continuation == null) throw new ArgumentNullException("continuation"); SynchronizationContext context = SynchronizationContext.Current; adapter.OnCompleted(delegate { if (SynchronizationContext.Current == context) continuation(); else context.Post(delegate(object state) { ((Action)state)(); }, continuation); }); } } }