C# 将Dispatchermer与BackgroundWorker和ProgressBar一起使用

C# 将Dispatchermer与BackgroundWorker和ProgressBar一起使用,c#,wpf,multithreading,backgroundworker,dispatchertimer,C#,Wpf,Multithreading,Backgroundworker,Dispatchertimer,我创建了一个简单的应用程序,每秒向ListView添加10倍的字符串并显示它。所有这些都是使用BackgroundWorker和显示添加进度的ProgressBar完成的。我的问题是,因为我听说暂停一个线程是非常危险的,并且可能会导致一些问题,我如何才能替换该线程。让我们假设一个调度员来睡觉? 如果我在这个列表中添加1000000个元素并报告进度会怎么样?在这种情况下,使用Thread.Sleep1还是其他方法更好 我的代码如下: private BackgroundWorker wor

我创建了一个简单的应用程序,每秒向ListView添加10倍的字符串并显示它。所有这些都是使用BackgroundWorker和显示添加进度的ProgressBar完成的。我的问题是,因为我听说暂停一个线程是非常危险的,并且可能会导致一些问题,我如何才能替换该线程。让我们假设一个调度员来睡觉? 如果我在这个列表中添加1000000个元素并报告进度会怎么样?在这种情况下,使用Thread.Sleep1还是其他方法更好

我的代码如下:

    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用于向UI线程报告BackgroundWorker的总体进度。这样,您可以显示进度并通知用户。但是,您正在使用它向listbox/listview实际添加字符串。在编译时最好将字符串文本添加到列表/数组中的内存缓冲区中,然后在后台工作程序完成后填充listbox/listview一次。如果您的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);           
}

调用线程。在工作线程上睡眠并不危险。很难看出像这样的代码的有用性。@HansPassant你说的有用性是什么意思?这只是一个例子。使用a,将间隔设置为适当的值,并更新progressbar?@Odrai实际上是一个分派器,因为我正在处理WPF。是的,当然,但问题是我不知道从哪里开始。你怎么知道它没有被更新?我把你的代码复制粘贴到我的项目中,一切都很好。如果您将int max设置为10000,您会在一段时间后看到更新的progressbar吗?10是一个非常小的值,而且你的计算机处理它的速度非常快,以至于你认为PB永远不会更新。