在BackgroundWorker线程上创建FlowDocument

3
我需要动态生成一个包含大量数据的FlowDocument。由于该过程需要几分钟时间,因此我希望在后台线程上执行操作,而不是让UI挂起。
但是,如果在非UI线程上生成FlowDocument,则尝试插入矩形和图像会导致运行时错误,提示它不是STA线程。
StackOverflow上有几个主题似乎涉及到我遇到的同样问题: 在第一个链接中,有人建议如下:
我建议使用 XamlWriter 并将 FlowDocument 序列化为 XDocument。序列化任务涉及到 Dispatcher,但一旦完成,您就可以对数据运行任意数量的并行分析,而 UI 中的任何内容都不会影响它。 (此外,一旦它是一个 XDocument,您可以使用 XPath 进行查询,这是一个相当好的工具,只要您的问题实际上是钉子。) 请问有人能详细解释一下作者的意思吗?

最终的FlowDocument被用来创建一个XpsDocument,然后使用XAML中的DocumentViewer控件将其显示为FixedDocumentSequence。 - JamesPD
你是否在后台线程生成内容之前,在UI线程上实例化了FlowDocument?或者类似的操作? - TheZenker
2个回答

2

对于未来的访问者

我曾经面临同样的问题,并通过这篇文章文章解决了所有问题。

最终我所做的是在后台线程上创建对象。

(Original Answer翻译成"最初的回答")

            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();

然后将结果写入内存流中作为xaml,这样我们就可以在主线程中读取它。"Original Answer"翻译成"最初的回答"。
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...

希望这能节省其他人的时间 :)

0

虽然这并不是对你引用的作者意思的详细阐述,但也许这可以成为你问题的解决方案: 如果你将自己挂钩到Application.Idle事件中,你可以在那里逐个构建你的FlowDocument。这个事件仍然在UI线程中,所以你不会像在后台工作器中那样遇到问题。 尽管如此,你必须小心不要一次做太多的工作,否则你会阻塞你的应用程序。 如果你能够将生成过程分成小块,你就可以在这个事件中逐个处理这些块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接