BackgroundWorker 和 WPF

3
我从System.ComponentMode.BackgroundWorker的DoWork方法中创建了一个WPF对象——FlowDocument,但我无法在WPF UI线程中访问它。
using System;
using System.Windows;
using System.Windows.Documents;
using System.ComponentModel;
namespace WpfApplication1
{
    public partial class MainWindow : Window
    {

        BackgroundWorker bw = new BackgroundWorker();

        public MainWindow()
        {
            InitializeComponent();

            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.RunWorkerAsync();
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {

            FlowDocument myFlowDocument = new FlowDocument();
            Paragraph myParagraph = new Paragraph();
            myParagraph.Inlines.Add(new Bold(new Run("Some bold text in the paragraph.")));
            myFlowDocument.Blocks.Add(myParagraph);

            e.Result = myFlowDocument;

        }

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //runtime error occured here.
            fviewer.Document = (FlowDocument)e.Result;
        }

    }
}

我听说当我在另一个线程中访问WPF对象时,需要使用dispatcher()方法。但是RunWorkerCompleted()不是UI的另一个线程,所以我感到困惑。 我该如何访问myFlowDocument?
3个回答

2
问题出在FlowDocument是在不同的线程中创建的,所以你需要在主UI线程上创建FlowDocument。然后在后台工作器中,你需要使用FlowDocument的Dispatcher.Invoke来设置属性和创建项。在您的简单示例中,使用后台工作器没有真正的优势,该工作器应该用于处理长时间运行的进程。
唯一的其他方法可能是在后台工作器中创建文档,将其序列化到内存流中,然后在返回到UI线程后进行反序列化。请注意保留HTML标签。

0
我在System.ComponentMode.BackgroundWorker的DoWork中创建了一个'FlowDocument',它是WPF对象。

但是请不要这样做。 UI对象需要在UI线程中创建和更新。

0
正如Bob Vale正确指出的那样,从来不要在另一个线程上创建UI对象是一条基本的经验法则。当您创建表示对象时,应该在UI线程上完成。后台任务应该返回简单的数据。我会把DoWork改成这样:
    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        //Assume some kind of "work" is being done here.
        e.Result = "Some bold text in the paragraph";
    }

然后,您可以通过Dispatcher设置文档内容:

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Action<string> action = r => 
        {
            FlowDocument myFlowDocument = new FlowDocument();
            Paragraph myParagraph = new Paragraph();
            myParagraph.Inlines.Add(new Bold(new Run(r)));
            myFlowDocument.Blocks.Add(myParagraph);
            fviewer.Document = myFlowDocument;
        };
        Dispatcher.Invoke(action, (string)e.Result);
    }

在这种情况下,Dispatcher 所做的是允许您将工作(在此情况下为委托)安排到拥有 UI 的线程上。

但是fviewer和流程文档是在不同的线程上创建的,所以您不能将它们合并。 - Bob Vale
@mjk6026 - 请尝试所做的修改。 - vcsjones

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