Search code examples
c#multithreadingwinformsbackgroundworkerbackground-thread

BackgroundWorker DoWork function is not being called


I've created a loading form within my C# WinForms application that is shown during long processes. I've added a progress bar to my loading form that I would like to update to give some feedback of loading to the user.

Within my loading form code, I have created a new BackgroundWorker and added DoWork and ProgressChanged event handlers. The problem is that the backgroundWorker_ProgressChanged is not being called. I have inserted break points into the function and they are not caught.

Where am I going wrong? Any help appreciated. Thanks.

frmLoading:

public frmLoading()
        {
            InitializeComponent();

            //check if bg worker is null
            if (backgroundWorker == null)
            {
                backgroundWorker = new BackgroundWorker();

                backgroundWorker.DoWork += backgroundWorker_DoWork;
                backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;

                
            }

            backgroundWorker.WorkerReportsProgress = true;

            //start
            backgroundWorker.RunWorkerAsync();
        }

backgroundWorker_DoWork:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                Thread.Sleep(100);
                backgroundWorker.ReportProgress(i);
            }
        }

backgroundWorker_ProgressChanged:

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //update value of progress bar
            progressBar1.Value = e.ProgressPercentage;
            //set the text of the progress bar
            this.Text = e.ProgressPercentage.ToString();
        }

Solution

  • Here's how you would do this with Progress<int> and Task.Run:

    public frmLoading()
    {
        InitializeComponent();
    
        IProgress<int> progress = new Progress<int>(p =>
        {
            //update value of progress bar
            progressBar1.Value = p;
            //set the text of the progress bar
            this.Text = p.ToString();
        });
    
        Task.Run(async () =>
        {
            for (int i = 1; i <= 100; i++)
            {
                await Task.Delay(TimeSpan.FromSeconds(0.1));
                progress.Report(i);
            }
        });
    }
    

    Personally I prefer Microsoft's Reactive Framework:

    public frmLoading()
    {
        InitializeComponent();
    
        Observable
            .Interval(TimeSpan.FromSeconds(0.1))
            .Take(100)
            .ObserveOn(this)
            .Select(p => p + 1)
            .Subscribe(p =>
            {
                //update value of progress bar
                progressBar1.Value = p;
                //set the text of the progress bar
                this.Text = p.ToString();
            });
    }