我想向WinForm添加多个进度条,以便监视嵌套循环中的三个可能很长的进程。我认为我应该只能使用一个后台工作线程,以下是可接受的实现:
这是我正在完成工作的班级:
class Class1
{
public static void UpdatePB(BackgroundWorker worker)
{
for (int i = 1; i <= 10; i++)
{
for (int ii = 1; ii <= 10; ii++)
{
for (int iii = 1; iii <= 10; iii++)
{
Thread.Sleep(10);
worker.ReportProgress(iii, "PB3");
}
Thread.Sleep(10);
worker.ReportProgress(ii, "PB2");
}
Thread.Sleep(10);
worker.ReportProgress(i, "PB1");
}
}
这是backgroundWorker ProgressChanged事件:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
switch (e.UserState.ToString())
{
case "PB1":
progressBar1.Value = e.ProgressPercentage;
this.label1.Text = e.ProgressPercentage.ToString();
break;
case "PB2":
progressBar2.Value = e.ProgressPercentage;
this.label2.Text = e.ProgressPercentage.ToString();
break;
case "PB3":
progressBar3.Value = e.ProgressPercentage;
this.label3.Text = e.ProgressPercentage.ToString();
break;
}
Application.DoEvents();
}
答案 0 :(得分:3)
好的,经过几个小时的搜索,我发现这个LINK让我弄明白我做错了什么。基本上,我正在做的是在BackgroundWorker线程上运行进度条,同时仍然在主UI线程上运行进程。我意识到这不是我应该做的,所以我现在正在运行BackgroundWorker线程上的所有内容。此外,您将在我的代码示例中看到,我需要维护两个单独的Progress栏并更新包含状态信息的richtext框。我很容易就能使用这个功能。这是我的最终解决方案:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace BackgroundWorkerThreadExample
{
public partial class Form1 : Form
{
public delegate void ProgressUpdatedCallaback(ProgressUpdatedEventArgs progress);
BackgroundWorker bw = new BackgroundWorker();
public Form1()
{
InitializeComponent();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
DatabaseProcessor.ProgressUpdated += new DatabaseProcessor.ProgressUpdatedEvent(ProgressUpdated);
DatabaseProcessor.GetData();
}
private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
bw.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
bw.RunWorkerAsync();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (bw.IsBusy == true)
{
bw.CancelAsync();
}
bw.Dispose();
}
private void ProgressUpdated(ProgressUpdatedEventArgs progressUpdated)
{
if (InvokeRequired)
{
Invoke(new ProgressUpdatedCallaback(this.UpdateProgress), new object[] { progressUpdated });
}
else
{
UpdateProgress(progressUpdated);
}
}
private void UpdateProgress(ProgressUpdatedEventArgs args)
{
ProgressBar pb = new ProgressBar();
Label lb = new Label();
if (args.Message == "")
{
if (args.PBNum == 1)
{
pb = progressBar1;
lb = label1;
}
else if (args.PBNum == 2)
{
pb = progressBar2;
lb = label2;
}
if (pb.Maximum != args.Total)
{
// initial setup
pb.Minimum = 0;
pb.Maximum = args.Total;
pb.Style = ProgressBarStyle.Continuous;
}
pb.Value = args.Processed;
if (args.Total > 0)
{
double progress = args.Processed / (args.Total * 1.0);
lb.Text = progress.ToString("P2");
}
}
else
{
this.richTextBox1.Text += args.Message;
//Goto last line
this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;
this.richTextBox1.ScrollToCaret();
}
//Application.DoEvents();
}
}
public static class DatabaseProcessor
{
public delegate void ProgressUpdatedEvent(ProgressUpdatedEventArgs progressUpdated);
public static event ProgressUpdatedEvent ProgressUpdated;
public static void GetData()
{
int total = 126;
Random randomGenerator = new Random();
for (int i = 0; i < total; i++)
{
// Do some processing here
double delay = (double)randomGenerator.Next(2) + randomGenerator.NextDouble();
int sleep = (int)delay * 1000;
System.Threading.Thread.Sleep(sleep);
RaiseEvent(1, total, i + 1);
RaiseEvent(0, 0, 0, string.Format("Processing Item {0} \r\n", i + 1));
for (int ii = 0; ii < total; ii++)
{
// Do some processing here
double delay2 = (double)randomGenerator.Next(2) + randomGenerator.NextDouble();
int sleep2 = (int)delay2 * 10;
System.Threading.Thread.Sleep(sleep2);
RaiseEvent(2, total, ii + 1);
}
}
}
private static void RaiseEvent(int pbNum, int total, int current, string message = "")
{
if (ProgressUpdated != null)
{
ProgressUpdatedEventArgs args = new ProgressUpdatedEventArgs(pbNum, total, current, message);
ProgressUpdated(args);
}
}
}
public class ProgressUpdatedEventArgs : EventArgs
{
public ProgressUpdatedEventArgs(int pbNum, int total, int progress, string message = "")
{
this.PBNum = pbNum;
this.Total = total;
this.Processed = progress;
this.Message = message;
}
public string Message { get; private set; }
public int PBNum { get; private set; }
public int Processed { get; private set; }
public int Total { get; private set; }
}
}
答案 1 :(得分:1)
嗯,你正在展示一个虚假的进度条...如果这是你想要的,那么这种一般的方法是可以的。以下是两项改进: