【发布时间】: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