一个后台工作线程和多个进度条 [英] One Background Worker Thread and Multiple Progress Bars
问题描述
我要多进度条增加一个WinForm,以监视三个是在一个嵌套循环可能很长的过程。我推测,我应该能够只使用一个后台工作线程,是下面的实现可以接受的:
下面是我所在班级的工作正在做:
类class1
{
公共静态无效UpdatePB(BackgroundWorker的工人)
{
为(INT I = 1; I< = 10;我++)
{
为(INT II = 1; II蛋白酶= 10;二++)
{
为(INT三= 1; 3&下; = 10;三++)
{
Thread.sleep代码(10);
worker.ReportProgress(三,PB3);
}
Thread.sleep代码(10);
worker.ReportProgress(二,PB2);
}
Thread.sleep代码(10);
worker.ReportProgress(ⅰPB1);
}
}
和这里是BackgroundWorker的ProgressChanged事件:
私人无效backgroundWorker1_ProgressChanged(对象发件人,ProgressChangedEventArgs E)
{
//改变进度向价值BackgroundWorker的进展。
开关(e.UserState.ToString())
{
案PB1:
progressBar1.Value = e.ProgressPercentage;
this.label1.Text = e.ProgressPercentage.ToString();
中断;
案PB2:
progressBar2.Value = e.ProgressPercentage;
this.label2.Text = e.ProgressPercentage.ToString();
中断;
案PB3:
progressBar3.Value = e.ProgressPercentage;
this.label3.Text = e.ProgressPercentage.ToString();
中断;
}
Application.DoEvents();
}
好吧,几个小时后,搜索,我发现这个的链接这使我找出我在做什么错。基本上,我在做什么是对一个BackgroundWorker线程中运行进度条仍然运行在主UI线程的过程。我意识到,这是不是我应该做的,所以我现在正在运行的线程BackgroundWorker的一切。此外,您将看到在我的代码示例中,我不得不保持两个独立的进度条,并更新状态信息的富文本框的要求。我能这个功能相当容易。这是我最终的解决方案:
使用系统;
使用System.ComponentModel;使用System.Windows.Forms的
;
命名空间BackgroundWorkerThreadExample
{
公共部分Form1类:表格
{
公众委托无效ProgressUpdatedCallaback(ProgressUpdatedEventArgs进度);
BackgroundWorker的体重=新的BackgroundWorker();
公共Form1中()
{
的InitializeComponent();
bw.WorkerReportsProgress = TRUE;
bw.WorkerSupportsCancellation = TRUE;
bw.DoWork + =新DoWorkEventHandler(backgroundWorker_DoWork);
bw.RunWorkerCompleted + =新RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
}
私人无效backgroundWorker_DoWork(对象发件人,DoWorkEventArgs E)
{
DatabaseProcessor.ProgressUpdated + =新DatabaseProcessor.ProgressUpdatedEvent(ProgressUpdated);
DatabaseProcessor.GetData();
}
私人无效backgroundWorker_RunWorkerCompleted(对象发件人,System.ComponentModel.RunWorkerCompletedEventArgs E)
{
bw.Dispose();
}
私人无效的button1_Click(对象发件人,EventArgs五)
{
bw.RunWorkerAsync();
}
私人无效Form1_FormClosing(对象发件人,FormClosingEventArgs E)
{
如果(bw.IsBusy ==真)
{
bw.CancelAsync();
}
bw.Dispose();
}
私人无效ProgressUpdated(ProgressUpdatedEventArgs progressUpdated)
{
如果(InvokeRequired)
{
调用(新ProgressUpdatedCallaback(this.UpdateProgress ),新的对象[] {progressUpdated});
}
,否则
{
的UpdateProgress(progressUpdated);
}
}
私人无效的UpdateProgress(ProgressUpdatedEventArgs参数)
{
进度PB =新的ProgressBar();
标签磅=新的Label();
如果(args.Message ==)
{
如果(args.PBNum == 1)
{
PB = progressBar1;
磅= LABEL1;
}
,否则如果(args.PBNum == 2)
{
PB = progressBar2;
磅= LABEL2;
}
如果(pb.Maximum = args.Total!)
{
//初始化设置
pb.Minimum = 0;
pb.Maximum = args.Total;
pb.Style = ProgressBarStyle.Continuous;
}
pb.Value = args.Processed;
如果(args.Total大于0)
{
双进展= args.Processed /(args.Total * 1.0);
lb.Text = progress.ToString(P2);
}
}
,否则
{
this.richTextBox1.Text + = args.Message;
//转到最后一行
this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;
this.richTextBox1.ScrollToCaret();
}
//Application.DoEvents();
}
}
公共静态类DatabaseProcessor
{
公众委托无效ProgressUpdatedEvent(ProgressUpdatedEventArgs progressUpdated);
公共静态事件ProgressUpdatedEvent ProgressUpdated;
公共静态无效的GetData()
{
INT总= 126;
随机randomGenerator =新的随机();
的for(int i = 0; I<全;我++)
{
//做一些处理这里
双延迟=(双)randomGenerator.Next(2)+ randomGenerator.NextDouble();
INT睡眠=(int)的延迟* 1000;
System.Threading.Thread.Sleep(睡眠);
的RaiseEvent(1,总,I + 1);
的RaiseEvent(0,0,0,的String.Format(处理中档案{0} \r\\\
,I + 1));
为(INT II = 0; II蛋白酶;全;二++)
{
//做一些处理这里
双DELAY2 =(双)randomGenerator.Next (2)+ randomGenerator.NextDouble();
INT SLEEP2 =(int)的DELAY2 * 10;
System.Threading.Thread.Sleep(SLEEP2);
的RaiseEvent(2,总,ⅱ+ 1);
}
}
}
私有静态无效的RaiseEvent(INT pbNum,诠释总,INT当前,字符串消息=)
{
如果(ProgressUpdated!= NULL)
{
ProgressUpdatedEventArgs ARGS =新ProgressUpdatedEventArgs(pbNum,总,目前,消息);
ProgressUpdated(参数);
}
}
}
公共类ProgressUpdatedEventArgs:EventArgs的
{
公共ProgressUpdatedEventArgs(INT pbNum,诠释总,诠释进步,串消息=)
{
this.PBNum = pbNum;
this.Total =总;
this.Processed =进展情况;
this.Message =消息;
}
公共字符串消息{搞定;私人集; }
公众诠释PBNum {搞定;私人集; }
公众诠释加工{搞定;私人集; }
公众诠释共{搞定;私人集; }
}
}
I want to add multiple progress bars to a WinForm in order to monitor three potentially long processes that are in a nested loop. I theorized that I should be able to use just one Background worker thread, is the following implementation acceptable:
Here is my Class where the work is being done:
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");
}
}
and here is the backgroundWorker ProgressChanged Event:
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();
}
Ok, after many hours of searching I found this LINK that enabled me to figure out what I was doing wrong. Basically, what I was doing was running the progress bar on a BackgroundWorker Thread while still running the process on the main UI Thread. I realized that this is not what I should be doing so I am now running everything on the BackgroundWorker thread. Additionally, you will see in my code example, I had a requirement to maintain two separate Progress bars and update a richtext box with status information. I was able to this functionality rather easily. Here is my final solution:
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; }
}
}
这篇关于一个后台工作线程和多个进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!