Thomas
Thomas

Reputation: 34198

My issue is regarding handling multiple backgroud worker and multiple progressbar

my main problem is when i add dynamically a progressbar on flowLayoutPanel1 for each request then how can i increase right progressbar value frombackgroundWorker1_ProgressChanged event

when user click on start button then i will call RunWorkerAsync function of background worker....it is fine. here i am writing a sample code and try to show my problem.

my form has one textbox, one button and one flowLayoutPanel1 with FlowDirection topdown.

when user enter any url in textbox and click on start button then i will start file download with BackGroundWorker and add one progress bar dynamically on flowLayoutPanel1. 10 file can be downloaded at a time. so when user enter ten url one after after one and click on submit button then ten file will be downloading in background.

my problem is how to increment 10 progress bar progress properly from backgroundWorker1_ProgressChanged event another issue is when any file download will complete then the progress bar for which it has been created will be removed from panel

here is my full code. please have a look and tell me what i need to do to achieve my task. if anyone see there is problem in my code for which a dead lock may appear then also please guide me how to avoid dead lock. here is my code

public partial class Form1 : Form
    {
        static int pbCounter = 1;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            ProgressBar pb = new ProgressBar();
            if (pbCounter <= 10)
            {
                pb.Width = txtUrl.Width;
                flowLayoutPanel1.Controls.Add(pb);
                pbCounter++;

                System.ComponentModel.BackgroundWorker backgroundWorker1 = new System.ComponentModel.BackgroundWorker();

                backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
                backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
                backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            // Get the BackgroundWorker that raised this event.
            System.ComponentModel.BackgroundWorker worker = sender as System.ComponentModel.BackgroundWorker;

            // Assign the result of the computation
            // to the Result property of the DoWorkEventArgs
            // object. This is will be available to the  
            // RunWorkerCompleted eventhandler.
            //#e.Result = ComputeFibonacci((int)e.Argument, worker, e);
        }

        // This event handler deals with the results of the
        // background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                //# "Canceled";
            }
            else
            {
                pbCounter--;
                // Finally, handle the case where the operation  
                // succeeded.
                //#resultLabel.Text = e.Result.ToString();
            }
        }

        // This event handler updates the progress bar.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

    }

MY UPDATED PART

 public partial class Form1 : Form
    {
        static int pbCounter = 1;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            ProgressBar pb = new ProgressBar();
            if (pbCounter <= 10)
            {
                //pb.Step = 10;
                pb.Minimum = 0;
                //pb.Maximum = 100;
                pb.Width = txtUrl.Width;
                flowLayoutPanel1.Controls.Add(pb);
                pbCounter++;

                MyBackgroundWorker backgroundWorker1 = new MyBackgroundWorker();
                backgroundWorker1.pbProgress = pb;
                backgroundWorker1.WorkerReportsProgress = true;   
                backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
                backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
                backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

                backgroundWorker1.RunWorkerAsync(txtUrl.Text);
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int input = int.Parse(e.Argument.ToString());
            for (int i = 1; i <= input; i++)
            {
                Thread.Sleep(2000);
                 (sender as MyBackgroundWorker).ReportProgress(i * 10);
                 if ((sender as MyBackgroundWorker).CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
            }
        }

        // This event handler deals with the results of the 
        // background operation. 
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown. 
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                //# "Canceled";
            }
            else
            {
                ProgressBar pb = (sender as MyBackgroundWorker).pbProgress;
                if (pb != null)
                {
                    //pb.Value = 100;
                    //pb.Update();

                    while (pb.Value <= pb.Maximum)
                    {
                        //Thread.Sleep(1000);
                        flowLayoutPanel1.Controls.Remove(pb);
                        break;
                    }

                }
                // Finally, handle the case where the operation  
                // succeeded.
            }
        }

        // This event handler updates the progress bar. 
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            ProgressBar pb = (sender as MyBackgroundWorker).pbProgress;
            pb.Refresh();

            //if (e.ProgressPercentage < pb.Maximum)
            //    pb.Value = e.ProgressPercentage + 10;

            pb.Value = e.ProgressPercentage ;
            Application.DoEvents();

        }

    }

public class MyBackgroundWorker : System.ComponentModel.BackgroundWorker
    {
        public ProgressBar pbProgress = null;
        public MyBackgroundWorker()
        {
        }

        public MyBackgroundWorker(string name)
        {
            Name = name;
        }

        public string Name { get; set; }
    }

Upvotes: 0

Views: 399

Answers (2)

1Mayur
1Mayur

Reputation: 3485

First declare a global dictionary and a GetInstance Method to access the form instance

public partial class Form1 : Form
{
Dictionary<String, ProgressBar> progressBars = new Dictionary<String, ProgressBar>();

static Form1 _form1 = null;

static int pbCounter = 1;

public Form1()
{
    InitializeComponent();
    _form1 = this;
}

public static Form1 GetInstance() {
    return _form1;
}

Then with each url you get and you must be creating pb for each of them, just add them in this dictionary too

progressBars.Add("file1", pb1);
progressBars.Add("file2", pb2);
progressBars.Add("file3", pb3);
progressBars.Add("file4", pb4);

Create a function in form.cs in which you can pass the progressbar and then you can manually set the value of it.

public void ProgessReport(ProgressBar pb, int value) 
        {
            if (pb.InvokeRequired) 
            {
                pb.Invoke(new MethodInvoker(delegate { ProgessReport(pb, value); }));
            } else 
            {
                pb.Value = value;
            }
        }

now from where you are downloading the file you just have to call

Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 10);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 20);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file1"], 100);

and when your second file downloads then

Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 10);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 20);
Form1.GetInstance().ProgessReport(Form1.GetInstance().progressBars["file2"], 100);

like this ..

Upvotes: 1

Arun
Arun

Reputation: 978

This is one way of doing it -

Create your own class inherited from BackgroundWorker, Add a public variable of type ProgressBar.

Each time you add a BackgroundWorker and Progressbar dynamically, pass the progressbar object to your class.

Your derived Class -

public class MyBackgroundWorker : BackgroundWorker
{
    public ProgressBar pbProgress = null;

    public void BackgroundWorker()
    {
    }
}

Button Event Code -

private void btnStart_Click(object sender, EventArgs e)
{
    ProgressBar pb = new ProgressBar();
    if (pbCounter <= 10)
    {
        pb.Width = txtUrl.Width;
        flowLayoutPanel1.Controls.Add(pb);
        pbCounter++;

        MyBackgroundWorker backgroundWorker1 = new MyBackgroundWorker();
        backgroundWorker1.pbProgress = pb;

        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

        backgroundWorker1.RunWorkerAsync();
    }
}

Progress Changed Event -

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        (sender as MyBackgroundWorker).pbProgress.Value = e.ProgressPercentage;
    }

Upvotes: 1

Related Questions