设置Backgroundworker MVVM,更新进度条

时间:2012-02-06 11:07:03

标签: c# wpf multithreading progress-bar

我有一个StartCommand类:

public class StartCommand : ICommand
{
    public void Execute(object parameter)
    {
        //Fill Listview1
        ...
        //Here I want to increase the Progressbarvalue   

        //Fill Listview2
        ...
        //Here again and so far..       
    }
}

点击MainWindow.xaml上的“开始”按钮(同时也是progressBar)时,将执行执行命令。

我想要的是,在列表视图加载时,在这些地方更新进度条(查看代码)。 如何设置Backgroundworker?

我尝试过类似的东西:

public class StartCommand : ICommand
    {
        MainWindow mainWindow;

        public StartCommand(MainWindow mainWindow)
        {
             this.mainWindow = mainWindow
        }

        public void Execute(object parameter)
        {
            //Fill Listview1
            ...
            mainWindow.backgroundWorker1.RunWorkerAsync(10);  

            //Fill Listview2
            ...
            mainWindow.backgroundWorker1.RunWorkerAsync(20);      
        }
    }

主窗口:

public partial class MainWindow : Window
{
    BackgroundWorker backgroundWorker1;

    public MainWindow()
    {
        InitializeComponent();
        InitializeBackgroundWorker();
    }

    private void InitializeBackgroundWorker()
    {
        backgroundWorker1.DoWork +=
            new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerCompleted +=
            new RunWorkerCompletedEventHandler(
        backgroundWorker1_RunWorkerCompleted);
        backgroundWorker1.ProgressChanged +=
            new ProgressChangedEventHandler(
        backgroundWorker1_ProgressChanged);
    }


    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        e.Result = UpdateProgressBar((int)e.Argument, worker);
    }

    private int UpdateProgressBar(int value, BackgroundWorker worker)
    {
        worker.ReportProgress(value);
        return Convert.ToInt32(progressBar.Value);
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

    }

    private void backgroundWorker1_ProgressChanged(object sender,ProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
    }
}

}

这不起作用(这只是一些复制/粘贴安排,因为我不知道如何实现这一点,第一次使用WPF中的Threads)。但也许你现在有了一个更好的景象,我正在寻找......

2 个答案:

答案 0 :(得分:3)

您必须选择:使用一个后台工作程序加载所有列表视图或使用多个后台工作程序,每个后台工作程序都填充一个列表视图。

目前,您正在尝试强制后台工作人员在上一个作业完成之前开始处理其他作业。

要快速解决此问题:将所有代码加载到DoWork处理程序中的listviews中。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    // fill listview1
    worker.ReportProgress(percentageDone);
    // fill listview2
    worker.ReportProgress(percentageDone);
    // fill listview3
    worker.ReportProgress(percentageDone);
}

要使用多个Backgroundworkers,请创建多个Backgroundworkers:

var bw1 = new BackgroundWorker();
bw1.DoWork += ...;
bw1.RunAsync(...);
var bw2 = new BackgroundWorker();
bw2.DoWork += ...;
bw2.RunAsync(...);
var bw3 = new BackgroundWorker();
bw3.DoWork += ...;
bw3.RunAsync(...);

答案 1 :(得分:2)

这完全取决于“填充列表视图”实际意味着什么。如果您要去数据库获取数据,那么肯定应该在后台线程上。但是,如果您已经拥有数据并且只需要填充列表视图,那么BackgroundWorker将无济于事 - 这将使事情变得更糟。那是因为你需要编组回UI线程才能访问ListView

如果要将大量数据添加到ListView并且您希望始终保持UI响应,则需要在单独的调度程序消息中以块的形式添加数据。添加块后,排队另一条消息以添加下一个块。这使得调度员有时间在列表填充时处理其他消息。