/// <summary> /// Runs the action inside a message loop and continues pumping messages /// as long as any asynchronous operations have been registered /// </summary> public static void Run(Action asyncAction) { using (InstallerAndRestorer.Install()) { // InstallerAndRestorer ensures the WinForms context is installed // capture that WinFormsContext var winFormsContext = SynchronizationContext.Current; // wrap the WinForms context in our own decorator context and install that var asyncVoidContext = new AsyncVoidSyncContext(winFormsContext); SynchronizationContext.SetSynchronizationContext(asyncVoidContext); // queue up the first message before we start running the loop var message = new AsyncActionLaunchMessage(asyncAction, asyncVoidContext); asyncVoidContext.Post(message.LaunchMessageImpl, state: null); // run the actual WinForms message loop Application.Run(); } }
public void LaunchMessageImpl() { // wrap the WPF context in our own decorator context and install that this.asyncVoidContext = new AsyncVoidSyncContext(SynchronizationContext.Current, frame); SynchronizationContext.SetSynchronizationContext(asyncVoidContext); // now invoke our taskFunction and store the result // Do an explicit increment/decrement. // Our sync context does a check on decrement, to see if there are any // outstanding asynchronous operations (async void methods register this correctly). // If there aren't any registerd operations, then it will exit the loop asyncVoidContext.OperationStarted(); try { asyncAction.Invoke(); } finally { asyncVoidContext.OperationCompleted(); } }
public AsyncActionLaunchMessage(Action asyncAction, AsyncVoidSyncContext postingContext) { this.asyncAction = asyncAction; this.postingContext = postingContext; }