2007-12-13

FlowDocument and multiple threads

Recently, I try to use the FlowDocumentScrollViewer to display FlowDocument's. So I create WPF window application that creates and displays flow documents with FlowDocumentScrollViewer.





The refresh button clears the contents of the documentPanel, and creates and displays a random number of flow documents.





This works as expected and creates a random number of flow documents on window.
My next step is to make this work in asynchronous manner. How is that possible? Enter DispatcherObject and WPF Threading model.
The basic technique is to use the Dispatcher methods and delegates to do the heavy operations in a different thread.
To demonstrate this, I create a new "Refresh Async" button and modify the flow document creation to include a 5 sec Sleep.
The next step is to add the delegate and dispatcher calls. The refresh async button handler uses the Dispatcher to asynchronously call the GenerateAndShowFlowDocumentHandler method which creates and displays the flow document.







This also works fine.

The next step is to create the FlowDocument in a separete thread and use the main UI thread for UI update.





When I try this I get exceptions!.








To resolve this issue, I should serialize the FlowDocument as Memory stream since FlowDocument's seems that they can’t serialize themselves on different threads.
Add the following before passing the flow document.









And to the handler :





And it works great!!

4 comments:

Sam said...

Hi Chris,
Your method works well to solve the threading exception but when checking its performance impact seems it performs badly (specifically the XamlWriter.Save)
Do you have any idea how the performance could be improved or maybe an alternative solution to the FlowDocument serialization issue?

Chris Mylonas said...

Unfortunately no...

Anonymous said...

thanks for this nice post 111213

Anonymous said...

While this works if the FlowDocument you are buildung is fairly big it takes a long time to marshal the memorystream across to the UI thread and then load into a viewers flowdocument.

Aaron has a similer blog entry at
http://www.wiredprairie.us/journal/2007/05/creating_wpf_flowdocuments_on.html

This sort of defeats the usefulness of background processing.

If one could build the xaml in parts and dispatch that across it might work better.