【问题标题】:Backgroundworker ProgressChanged acts after the worker is doneBackgroundworker ProgressChanged 在工作人员完成后执行
【发布时间】:2012-07-30 22:02:55
【问题描述】:

我创建了一个表单,每当我调用一个耗时的例程时,它都会弹出并显示一个进度条。我通过UpdateProgress 方法反馈我的例程进度。

我正在使用后台工作人员来允许用户移动表单并在此表单更新时继续开展业务。但是,表单会一直锁定,直到例程完成,然后快速将进度条增加到 100% 并退出(应该如此)。在 imo 中,进度条应该随着对 UpdateProgress 方法的调用进度而更新。

我在这里做错了什么?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace myNameSpace
{
    public partial class ProgressIndicator : Form
    {
        int progressPercentage;

        public ProgressIndicator()
        {
            InitializeComponent();
        }

        void progressUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // update the UI with appropriate fields
            progressBar.Value = e.ProgressPercentage;
            labelCommunicating.Text = "In progress: " + e.ProgressPercentage + "% complete";
        }

        void progressUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Close();
        }

        void progressUpdater_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                if (progressPercentage >= 100)
                {
                    break;
                }

                worker.ReportProgress(progressPercentage);

                Thread.Sleep(100);
            }
        }

        public void UpdateProgress(int progressPercentage)
        {
            this.progressPercentage = progressPercentage;
        }

        private void ProgressIndicator_Load(object sender, EventArgs e)
        {
            BackgroundWorker progressUpdater = new BackgroundWorker();
            progressUpdater.WorkerReportsProgress = true;
            progressUpdater.WorkerSupportsCancellation = true;
            progressUpdater.DoWork += new DoWorkEventHandler(progressUpdater_DoWork);
            progressUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(progressUpdater_RunWorkerCompleted);
            progressUpdater.ProgressChanged += new ProgressChangedEventHandler(progressUpdater_ProgressChanged);

            progressUpdater.RunWorkerAsync();
        }
    }
}

【问题讨论】:

  • 您发布的代码无法重现该问题。您在 DoWork 中使用 Sleep(),这将始终隐藏问题。但是真正的 DoWork 事件处理程序经常调用 ReportProgress。如果 UI 线程能够跟上速度,它就会开始落后。如果经常调用并且它无法完成其低优先级的职责。就像响应用户输入或绘制控件一样。它会看起来死了。人类只能以每秒 25 次的速度查看进度, 少于淹没 UI 线程所需的时间。
  • 嗯?在执行“工作”(DoWork 处理程序)时,您根本不会更新进度。另外,您甚至没有展示如何调用 UpdateProgress 的示例。通常,“进度”是完成工作的标志;这是由 DoWork 处理程序完成的。
  • Hans:添加了 sleep 以便应用程序不会占用资源。 Peter:工作在别处完成,DoWork 方法在这里所做的是检查进度并相应地更新屏幕。进度在UpdateProgress 方法中更改。

标签: c# winforms backgroundworker multithreading


【解决方案1】:

这听起来像是一个牵强的解决方案,我认为您的问题在于while loop。但是,更好的方法可能是通过使用 Invoke(); 来简单地更新您的 ProgressBar 而不会阻塞 UI,例如

Invoke(new myUpdate(updateProgress), pval);//call invoke whenever you need to update the progress bar assuming pval is an integer with the value to update with. This could be in a thread for instance.

//declare this as a class level delegate
private delegate void myUpdate(int progress);

//method to update progress bar
private void updateProgress(int progress)
{
    progressBar.Value = progress;
}

【讨论】:

  • 感谢您的回复!这似乎比我正在尝试做的要好得多。我在第一行出现错误,上面写着updateProgress。它表示updateProgress 在当前上下文中不存在。
  • 出了点小错误,现在已经更新了。确保所有方法、委托和调用都在您要更新进度的表单类中。
  • 我正在从另一个班级打来电话。我怎样才能使代码正确执行此操作?
  • 如果需要使用类,可以声明为对象,在主类中使用。例如MyWorker work = new MyWoker();Invoke(new myUpdate(updateProgress), work.Progress);
【解决方案2】:

您可以通过这种方式创建流程,而无需将调用包装在 Invoke 方法周围。

//delegate method
private delegate void updateProgressDelegate(int progress);

//actual method
private void updateProgress(int progress)
{
    if(this.InvokeRequired)
    {
        this.Invoke(new updateProgressDelegate(updateProgress), progress);
    }
    else
    {
        progressBar.value = progress;
    }
}

【讨论】:

    猜你喜欢
    • 2020-05-30
    • 2023-03-25
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    相关资源
    最近更新 更多