[英]Weird behavior of Background worker and multiple progress bar c#
我尝试模拟一个长时间运行的过程。 在我的应用程序中,我使用背景并动态添加进度栏。 当我单击开始按钮时,过程开始,面板上添加了进度条。 如果我只单击一次,则一切正常,但如果我单击两次或多次,则添加的进度条数量会增加,但最后的进度条进度会增加,最后其他进度条的进度会突然增加。
我想要添加任何数量的进度条,所有这些都应同时处理,而不是最后一个和最后一个。 就像许多进程在各自的上下文中同时运行一样,所有这些都应该在一起。 这是我的代码,我希望如果有人看一下它,那么他们可以理解缺陷所在。 请帮助我修复最后添加的进度条进度增加的漏洞。 如果可能,请运行我的代码并查看问题。
public partial class Form2 : Form
{
MyBackgroundWorker backgroundWorker1 = null;
Dictionary<string, string> dct = new Dictionary<string, string>();
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void btnStart_Click(object sender, EventArgs e)
{
backgroundWorker1 = new MyBackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerAsync(txtNumber.Text);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string strID = DateTime.Now.ToString("yyyyMMdd") + DateTime.Now.ToString("hhmmss")+DateTime.Now.Millisecond.ToString();
MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
tmpBg.Name = "bg_" + strID;
ProgressBar pb = new ProgressBar();
pb.Minimum = 0;
pb.Maximum = 100;
pb.Name = "pb_" + strID;
pb.Width = txtNumber.Width;
this.BeginInvoke((MethodInvoker)delegate
{
flowLayoutPanel1.Controls.Add(pb);
});
dct.Add(tmpBg.Name, pb.Name);
int input = int.Parse(e.Argument.ToString());
for (int i = 1; i <= input; i++)
{
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(i * 10);
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
}
// This event handler updates the progress bar.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
string strName = tmpBg.Name;
if (!string.IsNullOrEmpty(strName))
{
strName = strName.Substring(3);
ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0];
pb.Value = e.ProgressPercentage;
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
string strName = tmpBg.Name;
strName = strName.Substring(3);
ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0];
pb.Value = 100;
//MessageBox.Show("Done");
}
}
public class MyBackgroundWorker : System.ComponentModel.BackgroundWorker
{
public MyBackgroundWorker()
{
}
public MyBackgroundWorker(string name)
{
Name = name;
}
public string Name { get; set; }
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker);
string strName = tmpBg.Name;
strName = strName.Substring(3);
ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0];
//pb.Value = 100;
//MessageBox.Show("Done");
flowLayoutPanel1.Controls.Remove(pb);
}
我想我可以按您的意愿进行操作。
在ProgressChanged中,我以另一种方式获取进度条。
在DoWork中,我以进度百分比报告了当前backgroundWorker的进度。
我删除Thread.Sleep
是因为我认为这是引起问题的原因,因此在DoWork
添加了Console.WriteLine
来减慢程序速度(否则它比ProgressBar
呈现的速度更快)
public partial class Form2 : Form { MyBackgroundWorker backgroundWorker1 = null; Dictionary<string, string> dct = new Dictionary<string, string>(); public Form2() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void btnStart_Click(object sender, EventArgs e) { backgroundWorker1 = new MyBackgroundWorker(); backgroundWorker1.WorkerReportsProgress = true; backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); backgroundWorker1.RunWorkerAsync(int.Parse(txtNumber.Text)); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { string strID = DateTime.Now.ToString("yyyyMMdd") + DateTime.Now.ToString("hhmmss") + DateTime.Now.Millisecond.ToString(); MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker); tmpBg.Name = "bg_" + strID; ProgressBar pb = new ProgressBar(); pb.Minimum = 0; pb.Maximum = 100; pb.Name = "pb_" + strID; pb.Width = txtNumber.Width; this.BeginInvoke((MethodInvoker)delegate { flowLayoutPanel1.Controls.Add(pb); }); dct.Add(tmpBg.Name, pb.Name); int input = (int)e.Argument; for (int i = 1; i <= input; i++) { Console.WriteLine(tmpBg.Name + ": " + (i * 100 / input)); //for testing (this line slows the program down a lot) tmpBg.ReportProgress(i * 100 / input); if (tmpBg.CancellationPending) { e.Cancel = true; return; } } } // This event handler updates the progress bar. private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker); string strName = tmpBg.Name.Substring(3); ProgressBar pb; if (!string.IsNullOrEmpty(strName)) { foreach (Control c in flowLayoutPanel1.Controls) { if (c.Name == ("pb_" + strName)) { pb = (ProgressBar)c; pb.Value = Math.Min(100,e.ProgressPercentage); } } } } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { MyBackgroundWorker tmpBg = (sender as MyBackgroundWorker); string strName = tmpBg.Name; strName = strName.Substring(3); ProgressBar pb = (ProgressBar)this.flowLayoutPanel1.Controls.Find(("pb_" + strName), true)[0]; pb.Value = 100; //MessageBox.Show("Done"); } } public class MyBackgroundWorker : System.ComponentModel.BackgroundWorker { public MyBackgroundWorker() { } public MyBackgroundWorker(string name) { Name = name; } public string Name { get; set; } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.