Henry
Henry

Reputation: 195

ProgressBar form hangs on the middle, value updated from BackGroundWorker class

i have created a form1 with button1 to start a task, which will be processed on the background with BackGroundWorker on a separate class and display a ProgressBar on a separate window.

my problem is the process is working fine except that the task is done yet progressbar form hangs on the middle.

enter image description here

below is BackGroundLoading Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;

namespace sample2
{
    public class BackgroundLoading
    {
        public BackgroundWorker Bw;
        public delegate void RunFunction();
        public RunFunction thisFunction;
        mycontrols.LoadProgress p = new mycontrols.LoadProgress();

        public BackgroundLoading(RunFunction newFunction)
        {
            thisFunction = newFunction;
            Bw = new BackgroundWorker();
            Bw.WorkerReportsProgress = true;
            Bw.DoWork += new DoWorkEventHandler(Bw_DoWork);
            Bw.ProgressChanged += new ProgressChangedEventHandler(Bw_ProgressChanged);
            Bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bw_RunWorkerCompleted);
        }

        public void Start()
        {
            Bw.RunWorkerAsync();
        }

        void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }
            if (e.Cancelled)
            {
                MessageBox.Show("Cancelled!");
            }
            else
            {
                MessageBox.Show("Completed!");
                p.Close();
            }

        }

        public void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            /// If I put 
            /// p.ProgBar.Value = e.ProgressPercentage;
            /// the progressbar hangs upon form show.
        }

        void Bw_DoWork(object sender, DoWorkEventArgs e)
        {
            p.Show();

            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; (i <= 100); i++)
            {
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    if (thisFunction != null)
                    {
                        thisFunction();
                        worker.ReportProgress((i * 1));
                        p.ProgBar.Value = i;   
                    }
                    else
                    {
                        MessageBox.Show("Error, no method found");
                    }
                }
            }

        }
    }
}

this is the Form1 code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace sample2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BackgroundLoading BL = new BackgroundLoading(workingmethod);
            BL.Start();
        }

        private void workingmethod()
        {
            System.Threading.Thread.Sleep(10);
        }

    }
}

this is the code for the LoadProgress form

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace sample2.mycontrols
{
    public partial class LoadProgress : Form
    {
        public LoadProgress()
        {
            InitializeComponent();
        }

        private void LoadProgress_Load(object sender, EventArgs e)
        {     

        }

    }
}

no code on the progressbar form since update is done on the class. can't find the causing of hanging.

Thanks in Advance.

Upvotes: 1

Views: 1108

Answers (1)

Grant Winney
Grant Winney

Reputation: 66511

Show the form on the main UI thread, immediately prior to running your BackgroundWorker:

public void Start()
{
    p.Show();

    Bw.RunWorkerAsync();
}

Then you can make calls to the form in the ProgressChanged event, which runs on the UI thread.

Remove p.Show() and p.ProgBar.Value = i; from the DoWork event - you don't want to touch the UI thread from your background thread.

public void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    p.ProgBar.Value = e.ProgressPercentage;
}

Finally, close the form when the BackgroundWorker is complete (which you're already doing):

void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    p.Close();
}

Upvotes: 1

Related Questions