Creating FlowDocument on BackgroundWorker thread

和自甴很熟 提交于 2019-12-11 12:59:22

问题


I have the need to generate dynamically generate a FlowDocument from a large set of data. Because the process takes several minutes, I'd like to perform the operation on a background thread rather than have the UI hang.

However, I can't generate the FlowDocument on a non-UI thread otherwise attempts to insert rectangles and images cause run-time errors complaining that it's not STA thread.

There are a couple of threads on StackOverflow which seem to involve the same problem I'm having:

  • Accessing a WPF FlowDocument in a BackGround Process

  • WPF : Is it impossible to UI load in background thread?

In the first link someone suggests the following:

"What I'd do: use a XamlWriter and serialize the FlowDocument into an XDocument. The serialization task involves the Dispatcher, but once it's done, you can run as many wacky parallel analyses of the data as you want and nothing in the UI will affect it. (Also once it's an XDocument you query it with XPath, which is a pretty good hammer, so long as your problems are actually nails.)"

Can someone elaborate on what does the author mean by this?


回答1:


For any future visitors I faced the same problem and solved all thanks to this article article

What ended up doing is creating the object on a background thread

            Thread loadingThread = new Thread(() =>
        {
            //Load the data
            var documant = LoadReport(ReportTypes.LoadOffer, model, pageWidth);

            MemoryStream stream = new MemoryStream();
            //Write the object in the memory stream
            XamlWriter.Save(documant, stream);
            //Move to the UI thread
            Dispatcher.BeginInvoke(
               DispatcherPriority.Normal,
               (Action<MemoryStream>)FinishedGenerating,
               stream);
        });

        // set the apartment state  
        loadingThread.SetApartmentState(ApartmentState.STA);

        // make the thread a background thread  
        loadingThread.IsBackground = true;

        // start the thread  
        loadingThread.Start();

And then wrote the result in the memory stream as xaml so we can read it back in the main thread

void FinishedGenerating(MemoryStream stream)
    {
        //Read the data from the memory steam
        stream.Seek(0, SeekOrigin.Begin);
        FlowDocument result = (FlowDocument)XamlReader.Load(stream);

        FlowDocumentScrollViewer = new FlowDocumentScrollViewer
        {
            Document = result
        };
    //your code...

Wish it could save others some time :)




回答2:


While not realy an answer to elaborating on what the author of your quote means, maybe this can be a solution for your problem: If you hook yourself into the Application.Idle Event, you can build your FlowDocument one by one there. This event still is in the UI Thread so you won't get problems like in a background worker. Altho you have to be carefull not to do too much work at once, otherwise you will block your application. If it is possible to seperate your generation process into small chunks you can process those chunks one by one in this event.



来源:https://stackoverflow.com/questions/10313143/creating-flowdocument-on-backgroundworker-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!