C# Backgroundworker Progress在工作人员完成后更改了操作

C# Backgroundworker Progress在工作人员完成后更改了操作,c#,winforms,backgroundworker,multithreading,C#,Winforms,Backgroundworker,Multithreading,我创建了一个窗体,每当我调用一个耗时的例程时,它都会弹出并显示一个进度条。我通过UpdateProgress方法提供例程的进度 我正在使用一个后台工作程序,允许用户在表单更新时移动表单并继续执行其业务。然而,表单只是锁定,直到例程完成,然后快速将进度条倾斜到100%并退出(它应该退出)。依我看,进度条应该与调用UpdateProgress方法的进度一起更新 我做错了什么 using System; using System.Collections.Generic; using System.Co

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

我正在使用一个后台工作程序,允许用户在表单更新时移动表单并继续执行其业务。然而,表单只是锁定,直到例程完成,然后快速将进度条倾斜到100%并退出(它应该退出)。依我看,进度条应该与调用
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();
        }
    }
}

这听起来像是一个牵强的解决方案,我认为您的问题在于
while循环
。但是,更好的方法可能是只更新
ProgressBar
,而不使用
Invoke()阻塞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;
}

您可以以这种方式创建流程,这样就不需要围绕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;
    }
}

谢谢你的回复!这似乎比我想做的要好得多。我在第一行看到一个错误,上面写着
updateProgress
。它说,
updateProgress
在当前上下文中不存在。有一点错误,但它现在已更新。确保所有方法、委托和调用都在更新进度的表单类中。我正在从另一个类进行调用。如何使代码正确地执行此操作?如果需要使用类,可以将其声明为对象并在主类中使用。e、 g.
MyWorker工作=新的MyWoker()
Invoke(newmyupdate(updateProgress),work.Progress)
您发布的代码没有任何方法可以重新解决问题。您在DoWork中使用Sleep(),这将始终隐藏问题。但是真正的DoWork事件处理程序经常调用ReportProgress。如果UI线程跟上的速度越快,它就会开始落后。如果经常打电话,而它又没有抽出时间来履行其低优先级的职责。例如响应用户输入或绘制控件。它看起来会死的。人类只能以每秒25次的速度看到进度,远远低于淹没UI线程所需的速度。嗯?在执行“工作”(DoWork处理程序)时,根本不更新进度。另外,您甚至没有展示如何调用UpdateProgress的示例。通常,“进度”表示已完成的工作;这是由DoWork处理程序完成的。Hans:添加睡眠是为了使应用程序不占用资源。彼得:工作在别处完成,这里的
DoWork
方法做的是检查进度并相应地更新屏幕。在
UpdateProgress
方法中更改进度。