与Backgroundworker合作

时间:2014-02-06 17:38:01

标签: c# wpf backgroundworker

我想使用WPF-RichTextbox

BackgroundWorker中加载文字文件

这是我的代码:

    private delegate void update();

    private void reader()
    {
        StreamReader str = new StreamReader("C:\\test.txt");
        while (!str.EndOfStream)
        {
            richTextBox1.AppendText(str.ReadToEnd());
        }

    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        progress wnd = new progress();
        BackgroundWorker bg = new BackgroundWorker();
        bg.DoWork += delegate(object s, DoWorkEventArgs args)
        {

            update up = new update(reader);
            richTextBox1.Dispatcher.Invoke(up);

        };

        bg.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {

            wnd.Close();
        };

        wnd.Show();
        bg.RunWorkerAsync();



    }

和progress.xaml:

   <Window x:Class="WpfApplication3.progress"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="progress" Height="192" Width="452" ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True" WindowStartupLocation="CenterScreen" WindowStyle="None">
<Grid>
    <Label Content="loading ...." Height="28" HorizontalAlignment="Left" Margin="46,32,0,0" Name="label1" VerticalAlignment="Top" />
    <ProgressBar Height="29" HorizontalAlignment="Left" Margin="46,78,0,0" Name="progressBar1" VerticalAlignment="Top" Width="325" IsIndeterminate="True" />
</Grid>

当我设置wnd.showdialog()时,它会显示进度条的不确定状态,但应用程序不会加载任何文本。

当我设置wnd.show()时,它会加载文本,但加载时,进度条会冻结 没有表现出不确定的状态。

感谢您的帮助。

编辑:

由于Servey和SLaks的答案,我更新了代码,但它有同样的问题(它加载文本但加载时,进度条冻结,并且不显示不确定状态。)

有什么问题?这是我更新的代码:

           StringBuilder sb = new StringBuilder();



    private void reader()
    {
        StreamReader str = new StreamReader("C:\\test.txt");
        while (!str.EndOfStream)
        {

            sb.Append(str.ReadToEnd());

        }

    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        progress wnd = new progress();
        BackgroundWorker bg = new BackgroundWorker();
        bg.DoWork += delegate(object s, DoWorkEventArgs args)
        {



            reader();

        };

        bg.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {
            richTextBox1.AppendText(sb.ToString());
            wnd.Close();

        };

        wnd.Show();
        bg.RunWorkerAsync();


    }

2 个答案:

答案 0 :(得分:1)

你实际上并没有在后台做任何工作。您正在启动后台工作程序,而后台工作人员在后台执行的唯一操作就是安排在UI线程上运行的操作,并且该操作是您执行所有非UI工作的地方。由于您在UI线程上进行非UI工作,因此在完成之前不能执行任何其他图形操作。

您需要从BGW的do work事件中读取文件,将其存储在内存中,然后在UI线程中运行的Completed事件中,然后将该数据放入UI中。

答案 1 :(得分:1)

好的,我已经查看了您上传的代码,您的问题很可能与您的负载有关。就您的加载而言,以下代码可以按您的要求完成工作:

MainWindow.xaml.cs

public MainWindow()
{
    InitializeComponent();

    Loaded += OnLoaded;
}

private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    Loaded -= OnLoaded;

    var wnd = new ProgressWindow();
    var dispatcher = wnd.Dispatcher;

    Task.Factory.StartNew(() =>
    {
        using (var stream = new StreamReader("C:\\test.txt"))
            return stream.ReadToEnd();

    }).ContinueWith(x =>
    {
        //Main window dispatcher
        Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => richTextBox1.AppendText(x.Result)));

        //progress window dispatcher
        dispatcher.Invoke(DispatcherPriority.DataBind, new Action(wnd.Close));
    });

    wnd.ShowDialog();
}

虽然这可以按预期工作,但无论如何都会发生冻结(我冻结了几秒钟加载一个800kb的文本文件)。问题是您使用RichTextBox。根据您的代码判断,您不知道wfp是如何工作的,并且您正在尝试以典型的winform风格工作。

Wpf中的

RichTextBox与winforms RichTextBox非常不同。同样,TextBlock与典型的Label非常不同。如果您想要的只是颜色和其他格式选项,TextBlock能够独立完成此操作,并且比构建RichTextBox的方式快得多。

如果您必须从文本文件构建RichTextBox,则需要了解FlowDocument以及如何自己创建文本文件以避免冻结。这个解决方案的替代方案是运行两个UI线程(每个窗口一个),你很可能会发现它比它的价值更麻烦。

在尝试此类事情之前,您应该先排序WPF基础知识并学习典型的MVVM模式,然后再深入了解WPF世界。再次,如果可以,请避免在WPF中使用RTB。如果您知道如何使用它们,WPF中的基本控件比它们的winforms功能强大得多。