简体   繁体   中英

Weird behavior of Background worker and multiple progress bar c#

i try to simulate a bit long running process. in my app i use Background and add progress bar dynamically. when i click on start button then a process start and a progress bar added on panel. if i just click once then everything works fine but if i click twice or more then that number of progress bar getting added but the last progress bar progress are incremented and at last other progress bar progress incremented suddenly.

i want whatever number of progress bars are added all should process simultaneously not last one first and first one last. all should go together like many process are running simultaneously in their own context. here is my code and i hope if some one look at it then they can understand where is the flaw. please help me fix the flaw for which last added progress bar progress incremented. if possible run my code and see the problem.

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; }
        }

UPDATE Portion

 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);
        }

I think I got it working how you want it to.

  1. In ProgressChanged, I get the progressbar another way.

  2. In DoWork, I report progress as a percentage and from the current backgroundWorker.

  3. I removed Thread.Sleep because I think it was causing problems, added Console.WriteLine in DoWork to slow down program (otherwise it's faster than the ProgressBar renders)

     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; } } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM