将 DispatcherTimer 与 BackgroundWorker 和 ProgressBar 一起使用

Using DispatcherTimer with a BackgroundWorker and a ProgressBar

我创建了一个简单的应用程序,它每秒向 ListView 添加 10 次字符串并显示它。所有这些都是使用 BackgroundWorker 和显示添加进度的 ProgressBar 完成的。我的问题是,因为我听说暂停线程非常危险并且会导致几个问题,所以我如何用比方说 DispatcherTimer 替换 Thread.Sleep? 如果我向这个列表添加 1000000 个元素并报告进度怎么办?在这种情况下使用 Thread.Sleep(1) 还是其他更好?

我的代码如下:

    private BackgroundWorker worker = new BackgroundWorker();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnAggiungi_Click(object sender, RoutedEventArgs e)
    {
        worker.WorkerReportsProgress = true;
        worker.DoWork += worker_DoWork;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync();
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        String text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
        int min;
        int max = 10;

        for (min = 1; min <= max; min++)
        {
            int progressPercentage = Convert.ToInt32((double)min / max * 100);
            worker.ReportProgress(progressPercentage, text);
            Thread.Sleep(100);
        }
    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        pb.Value = e.ProgressPercentage;
        lstLoremIpsum.Items.Add(e.UserState.ToString());
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        lblCompleted.Content = "Done";
    }

截图:

经过一些测试:

worker.ReportProgress的意思是将BackgroundWorker的整体进度反馈给UI线程。这样您就可以显示进度并通知您的用户。但是,您正在使用它实际将字符串添加到列表框/列表视图。您最好在内存中(列表/数组中的缓冲区)编译添加字符串(文本),然后在后台工作人员完成时填充列表框/列表视图一次。如果您的 GUI 仍然冻结,请添加每 50、100 或 200 的字符串。

还有另一个小改进:

private void UpdateProgressbar(int percentage)
{
    if (InvokeRequired)
    {
        this.BeginInvoke(new Action<int>(UpdateProgressbar), new object[] { percentage });
        return;
    }

    pb.Value = percentage;
}

private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    UpdateProgressbar(e.ProgressPercentage);           
}