繁体   English   中英

BackgroundWorker和WPF

[英]BackgroundWorker and WPF

我从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?

问题是因为FlowDocument是在与UI线程不同的线程中创建的。

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

唯一的另一种方法可能是在后台工作程序中创建文档,将其序列化为内存流,然后在返回UI线程后反序列化。

正如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设置Document内容:

    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的线程安排工作(在本例中为委托)。

我从System.ComponentMode.BackgroundWorker的DoWork制作了一个'FlowDocument',一个WPF对象

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM