How to make a progressbar run in a different thread in C#

11,485

Solution 1

Instead of the ProgressBar, you should really move your long-running, non-UI code into a separate thread. The standard and easier way of doing this in WinForms is to use BackgroundWorker component, which can raise ProgressChanged event where you can update your UI. Important to note that ProgressChanged event is raised on the UI thread, not on the worker thread, so you don't even need to use Invoke() to perform UI operations (such as updating your ProgressBar).

Solution 2

Instead of using main thread for large processing you can use the Background worker for all the processing.

Here's a simple example to do it.

public partial class Form1 : Form
    {
        BackgroundWorker bgw = new BackgroundWorker();       
        public Form1()
        {
            InitializeComponent();
            label1.Text = "";
            label2.Text = "";
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
            bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
            bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
            bgw.WorkerReportsProgress = true;
            bgw.RunWorkerAsync();
        }

        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            int total = 57; //some number (this is your variable to change)!!

            for (int i = 0; i <= total; i++) //some number (total)
            {
                System.Threading.Thread.Sleep(100);
                int percents = (i * 100) / total;
                bgw.ReportProgress(percents, i);
                //2 arguments:
                //1. procenteges (from 0 t0 100) - i do a calcumation 
                //2. some current value!
            }
        }

        void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label1.Text = String.Format("Progress: {0} %", e.ProgressPercentage);
            label2.Text = String.Format("Total items transfered: {0}", e.UserState);
        }

        void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
             //do the code when bgv completes its work
        }
    }

Solution 3

you must use Control.Invoke for avoid cross-threading problem,but I prefer use BackgroundWorker for resolve it, create Form6 on a _field and use progressbar in ProgressChanged event for more information see this page

public void thread()
       {
          Form6 for6=null;
          Application.OpenForms[0].Control.Invoke(delegate{
            for6 = new Form6();
            for6.Show();
      });
   }
Share:
11,485
Lucas Juan
Author by

Lucas Juan

Updated on June 28, 2022

Comments

  • Lucas Juan
    Lucas Juan almost 2 years

    I want to create a basic multi-thread application using a progress bar. Meaning that this progress bar will run on a different thread while the main thread is busy in the large process it is doing. I've seen a lot of tutorials about it. But the thing that they are multi-threading is the one that doing the large process. The progress bar in the other form is just showing a simple progress bar that runs and complete using a timer.

    This is the code I have now.

    For the thread:

    public void thread()
    {
      Form6 for6 = new Form6();
      for6.Show();
    }
    
    
    TH1 = new Thread(thread);
    TH1.Start();
    

    For the progress bar (Code inside form 6)

     private void timer1_Tick(object sender, EventArgs e)
        {
            progressBar1.Increment(+1);
            if (progressBar1.Value == 99)
            {
                this.Close();
            }
        }
    
        private void Form6_Load(object sender, EventArgs e)
        {
            timer1.Start();
        }
    

    My problem is the thread in here doesn't run the Form6. Is there any way for me to do this?