« Separated at birth? JavaFX and WPF/XAML? | Main | Death of the Desktop with Aza Raskin »

Creating WPF FlowDocuments on the non-UI thread

From a post on the MSDN forums came a great question:

How to create and populate a FlowDocument on a thread other than the UI thread?

Here's what happens normally:

The calling thread cannot access this object because a different thread owns it.

Arggh.

FlowDocuments aren't freezable (yet they are DependencyObjects). That means they can't be created on one thread and then used on another. Bummer.

Two solutions came to mind:

  1. Do as much work as possible on the non-UI thread, prepping data, etc. Then, at the last possible moment, Invoke a method back in the UI thread and build the flow document.
  2. Cheat! Create the FlowDocument in the background thread. Then, save it as a Xaml file to memory, and reload it in the UI thread! Something like this:
      FlowDocument doc = new FlowDocument(new Paragraph(new Run("hi")));
      System.IO.MemoryStream stream = new System.IO.MemoryStream();
      XamlWriter.Save(doc, stream);
      stream.Position = 0;
      
      this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ZeroDelegate)delegate()
        {
          flowDoc = (FlowDocument) XamlReader.Load(stream);
        }
      );

I'm not sure what the performance characteristics would be of either option -- so you'll need to do some testing. I'd love to hear that there's a better way -- it' s not obvious though and doesn't follow the typical pattern for dealing with this type of stuff. It's very unfortunate that the document can't be manipulated / locked / etc. on another thread. That seems like an obvious use-case that many applications would want to do.

Help support my web site by searching and buying through Amazon.com (in assocation with Amazon.com).