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:
- 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.
- 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.