【问题标题】:Creating FlowDocument on BackgroundWorker thread在 BackgroundWorker 线程上创建 FlowDocument
【发布时间】:2012-04-25 09:45:56
【问题描述】:

我需要从大量数据中动态生成FlowDocument。因为这个过程需要几分钟,所以我想在后台线程上执行操作,而不是让 UI 挂起。

但是,我无法在非 UI 线程上生成 FlowDocument,否则尝试插入矩形和图像会导致运行时错误,抱怨它不是 STA 线程。

StackOverflow 上有几个线程似乎涉及我遇到的相同问题:

在第一个链接中,有人提出以下建议:

“我会做什么:使用XamlWriter 并将FlowDocument 序列化为XDocument。序列化任务涉及Dispatcher,但一旦完成,您可以运行尽可能多的古怪根据需要对数据进行并行分析,UI 中的任何内容都不会影响它。(同样,一旦它是 XDocument,你就可以使用 XPath 查询它,这是一个很好的锤子,只要你的问题实际上是钉子。) "

有人能详细说明一下作者的意思吗?

【问题讨论】:

  • 最终的 FlowDocument 然后用于创建 XpsDocument,然后使用 XAML 中的 DocumentViewer 控件将其显示为 FixedDocumentSequence。
  • 在后台线程开始生成内容之前,您是否在 ui 线程上实例化了流文档?或类似的东西?

标签: c# serialization backgroundworker flowdocument xamlwriter


【解决方案1】:

对于任何未来的访客 由于这篇文章,我遇到了同样的问题并解决了所有问题 article

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

            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 写入内存流中,以便我们可以在主线程中读回它

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

希望它可以为其他人节省一些时间:)

【讨论】:

    【解决方案2】:

    虽然不能真正回答详细说明您引用的作者的含义,但也许这可以解决您的问题: 如果您将自己挂接到 Application.Idle 事件中,您可以在那里一一构建您的 FlowDocument。此事件仍在 UI 线程中,因此您不会遇到像在后台工作人员中那样的问题。 尽管你必须小心不要一次做太多的工作,否则你会阻止你的应用程序。 如果可以将您的生成过程分成小块,您可以在此事件中逐个处理这些块。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-10
      • 2013-03-19
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多