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
方法中更改进度。