tags:

views:

150

answers:

1

We load FixedPage objects from an XPS document, process and displays it.The following code does the loading of the FixedPage from a Package:

        FixedPage fp = null;
        Package package;   // xps package
        Uri packageUri;    // uri of the package in the package store
        Uri fixedPageUri;  // uri of the fixed page
        Dispatcher _mainDispatcher // reference to the main dispatcher, passed to this function
                                   // this function runs in a different thread

        // get the fixed page stream
        Stream stream = package.GetPart(fixedPageUri).GetStream();

        // create a parser context to help XamlReader with the resources used in the page
        ParserContext pc = new ParserContext();
        pc.BaseUri = PackUriHelper.Create(packageUri, fixedPageUri);

        _mainDispatcher.BeginInvoke(
                    new UIRenderDelegate(delegate()
                    {
                        // this line takes its sweet time
                        fp = XamlReader.Load(stream, pc) as FixedPage;
                        stream.Dispose();
                    }), null).Wait();                       


        // return the created fixed page;

However, that XamlReader.Load() call takes a long time (especially for complex FixedPages) and sometimes blocks the UI. We could do this in another thread with it's own Dispatcher, but since the FixedPage class is not freeazable, its can't be used by the main UI thread.

Is there a way around this? Right now we're stuck rendering the FixedPages as images using RenderTargetBitmap since BitmapSource is Freezable.

A: 

Load the xaml into a memory stream first and them pass the memory stream to the UI thread. Parse the memorystream on the UI thread. This way you could do the slow file IO on he background thread. Only the inmemeory parsing of the stream (using XamlReader.Load) would be done on the UI Thread.

This artice explains how to do it.

bitbonk
This function is already running in a different thread. The begin invoke is there to run the Load on the UI thread.
moogs
Yes I am aware of that. My point was that you keep your two threads and pass the data from one thead to the other once it has been loaded to memory. The XamlReader.Load will be much faster now so it can be done on the UI Thread (not in the background thread anymore). In your scenario XamlReader.Load() takes a long time because of all the file IO. Once the data is in the MemoryStream it will not take that much time anymore. I had exactly the same problem and it worked for me.
bitbonk
Ok, one thing not clear aobut here is that the Stream is in memory. (We create a single-page package). I still don't get the other part of what you're saying [" so it can be done on the UI Thread (not in the background thread anymore).."] as the XamlReader.Load call IS IN the UI Thread.
moogs
Yes the XamlReader.Load is still in the UI Thread. BUT it is now much faster because it does not have to load the XAML text from the file. It now already in memory. This heavy work is done in the background thread where the UI is not blocked.
bitbonk
You pass the memorystream to the UIThread and then call XamlReader.Load on the MemoryStream.
bitbonk