title: What's the best way to create a new UI thread and call back methods on the original thread?
body: <p>I'm writing a plug-in class for a third-party GUI application. The application calls the <code>Run</code> method of my class, passing me a vendor-defined <code>Context</code> object. Any methods or properties in this <code>Context</code> object <strong>must be called from the current thread</strong> (that is, the application's UI thread).</p>
  
  <p>My plug-in code creates a WPF <code>Window</code> and shows it to the user. Some interactions need to call the <code>Context</code> object's methods, but some take time to run. This, of course, freezes my UI. Normally, I would call slow methods from a separate thread, but in this case I can't do that because the <code>Context</code> object is tied to the application's UI thread.</p>
  
  <p>Here's an example implementation of my Plugin class:</p>
  
  <pre><code>public class Plugin
  {
      public void Run(Context context)
      {
          // Create a window with my custom user interface
          var window = new MyWindow();
  
          // Call a slow method when MyButton is clicked
          window.MyButton.Click += (o, e) =&gt; context.SlowMethod();
  
          // Prevent exiting this Run method until the window is closed
          window.ShowDialog();
      }
  }
  </code></pre>
  
  <p><strong>What are some possible solutions that would allow me to call slow methods in the <code>Context</code> object (bound to the UI thread) while having a responsive UI?</strong></p>
  
  <p>One solution I've come up with is to create a second thread on which to run my UI and use the original thread to call <code>Context</code> methods. However, my implementation is rather complex, so I'd like to know if there's a more straightforward way to achieve this.</p>
  
  <p>Here's my current solution:</p>
  
  <pre><code>public class Plugin
  {
      public void Run(Context context)
      {
          // Get the application's UI thread dispatcher
          var dispatcher = Dispatcher.CurrentDispatcher;
  
          // Create a dispatcher frame to push later
          var frame = new DispatcherFrame();
  
          // Create a new UI thread (using an StaTaskScheduler)
          Task.Factory.StartNew(async () =&gt;
          {
              var window = new MyWindow();
  
              // The Click event handler now uses the original
              // thread's dispatcher to run the slow method
              window.MyButton.Click += async (o, e) =&gt;
                  await dispatcher.InvokeAsync(() =&gt; context.SlowMethod());
  
              window.ShowDialog();
  
              // When the window is closed, end the dispatcher frame
              frame.Continue = false;
          }, CancellationToken.None, TaskCreationOptions.None, new StaTaskScheduler(1));
  
          // Prevent exiting this Run method until the frame is done
          Dispatcher.PushFrame(frame);
      }
  }
  </code></pre>
  
  <p>The <code>StaTaskScheduler</code> schedules tasks in an STA thread (as required by WPF). It comes from the <a href="https://www.nuget.org/packages/MSFT.ParallelExtensionsExtras/" rel="nofollow noreferrer">Parallel Extensions Extras</a> library. </p>