6

Currently I'm aware of the following Dispatcher objects.

  • If you have a text view, you can use IWpfTextView.VisualElement.Dispatcher.

  • If your class is constructed by MEF (marked with [Export] and not directly constructed from your own code), then you can use the fact that the MEF part resolution algorithm and construction occurs on the UI thread, allowing the use of Dispatcher.CurrentDispatcher. For example:

    [Export(typeof(ISomeInterface))]
    public class MyClass : ISomeInterface {
      private readonly Dispatcher _dispatcher;
    
      public MyClass() {
        _dispatcher = Dispatcher.CurrentDispatcher.
      }
    }
    
  • You can use Application.Current.Dispatcher from any code.

What, if any, is the recommended practice for obtaining a Dispatcher?

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • The web editor takes your second approach (essentially) with `WebEditor.Dispatcher` – SLaks Feb 17 '14 at 04:14
  • Are you sure you need one? Why not capture `SynchronizationContext.Current` instead? – Stephen Cleary Feb 17 '14 at 06:15
  • 1
    Do not rely on SynchronizationContext.Current being the UI thread sync context. A MEF part can be instantiated on any thread. The fact that most MEF parts are triggered into existence from packages (which do load on the UI thread) doesn't mean anything, it's just a coincidence. – Kirill Osenkov Feb 17 '14 at 07:54
  • @StephenCleary: How does that help? You still need to figure out where to capture it. – SLaks Feb 17 '14 at 13:45
  • 1
    @SLaks: I encourage people (as much as possible) to depend on the context capture/resume of `await` first, then `SynchronizationContext`, with `Dispatcher`/`ISynchronizeInvoke`/`CoreDispatcher` last. – Stephen Cleary Feb 17 '14 at 14:05
  • 1
    @StephenCleary There are cases in Visual Studio where certain non-UI operations must be executed on the UI thread. One example of this is [`IVsOutputWindow.CreatePane`](http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.ivsoutputwindow.createpane.aspx). Using a proper `Dispatcher` is one way to ensure this call is always executed on the correct thread, regardless of the manner in which the MEF part was instantiated. `async`/`await` are of little use when the operation doesn't start on the correct thread. – Sam Harwell Feb 17 '14 at 14:27
  • @280Z28: Right. It's not always possible to avoid `Dispatcher`, and from Kirill's answer below it sounds like MEF is one of those cases. I just discourage its use in the general sense. – Stephen Cleary Feb 17 '14 at 16:23

1 Answers1

2

Do not take a dependency on MEF composing on UI thread. If it works for you right now, you're just getting lucky. Also MEF is delayed in nature and full of Lazy, so if you happen to realize it on a background thread, the entire subgraph will get realized on background.

I would use #1 or #3 (doesn't matter which, there is only one UI thread dispatcher, doesn't matter how you get to it).

Kirill Osenkov
  • 8,786
  • 2
  • 33
  • 37
  • Apparently, `Microsoft.Internal.VisualStudio.PlatformUI.BackgroundDispatcher` makes its own dispatchers on background threads. – SLaks Feb 17 '14 at 13:48