后台工作人员和WPF

后台工作人员和WPF,wpf,multithreading,backgroundworker,Wpf,Multithreading,Backgroundworker,我从System.ComponentMode.BackgroundWorker的DoWork中创建了一个“FlowDocument”,一个WPF对象,但我无法在WPF UI线程中访问它 using System; using System.Windows; using System.Windows.Documents; using System.ComponentModel; namespace WpfApplication1 { public partial class MainWin

我从System.ComponentMode.BackgroundWorker的DoWork中创建了一个“FlowDocument”,一个WPF对象,但我无法在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?

正如Bob Vale正确指出的那样;一般的经验法则是永远不要在另一个线程上创建UI对象。创建表示对象时;您应该在UI线程上执行此操作。后台任务应该返回简单数据。我会把嫁妆改成这样:

    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";
    }
然后,您可以通过以下方式设置文档内容:

private void bw\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
动作动作=r=>
{
FlowDocument myFlowDocument=新的FlowDocument();
段落My段落=新段落();
添加(新粗体(新运行(r));
myFlowDocument.Blocks.Add(My段落);
fviewer.Document=myFlowDocument;
};
调用(操作,(字符串)e.Result);
}

在本例中,Dispatcher所做的是允许您针对拥有UI的线程安排工作(本例中为委托)。

问题在于,FlowDocument是在与UI线程不同的线程中创建的

您需要在主UI线程上创建流文档。然后在后台工作程序中,您必须使用flow documents Dispatcher.Invoke来设置属性并创建项。在您的简单示例中,使用后台工作程序没有真正的优势。工作进程应该用于处理长时间运行的进程

唯一的其他方法可能是在后台工作程序中创建文档,将其序列化为内存中的流,然后在返回到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;
        }

    }
}
我从System.ComponentMode.BackgroundWorker的DoWork中创建了一个“FlowDocument”,一个WPF对象


不要那样做。需要从UI线程创建和更新UI对象。

但是fviewer和flow文档是在不同的线程上创建的,因此您不能将它们组合起来。@mjk6026-请尝试所做的修改。
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;
        }

    }
}