Ras
Ras

Reputation: 628

Backgroundworker ReportProgress event does not fire

I've a backgroundworker which take care of a timer in my application. This is the code:

    protected override void OnLoad(EventArgs e)
    {
        // Inizializzo il backgroundworker 
        bgwTimer.WorkerReportsProgress = true;
        bgwTimer.WorkerSupportsCancellation = true;
        bgwTimer.DoWork += (bgwTimer_DoWork);
        bgwTimer.RunWorkerCompleted +=(bgwTimer_RunWorkerCompleted);
        bgwTimer.ProgressChanged += (bgwTimer_ProgressChanged);
    }

    void bgwTimer_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    void bgwTimer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        throw new NotImplementedException();
    }

Basically the event "ProgressChanged" is never fired and so I cannot update the status of a progressbar. The event DoWork is linked to this method:

    void bgwTimer_DoWork(object sender, DoWorkEventArgs e)
    {
        int i = 0;
        if (bgwTimer.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            while (bgwTimer.IsBusy)
            {                
                Thread.Sleep(1000);
                bgwTimer.ReportProgress(i);
                refreshTimer();
            }
        }
    }

By my side the code looks good and it runs fine. As you can see the ReportProgress method is called but the event is not fired. Any hints?

UPDATE: Whops! I found that the event "bgwTimer_ProgressChanged" is fired only if I run the RunWorkerAsync right after the declaration of event. Basically:

bgwTimer.ProgressChanged += (bgwTimer_ProgressChanged); bgwTimer.RunWorkerAsync(); //this works!

Since I run the worker when the user press a button, the event is not triggered.


Here's the code of click event button:

    private void btnNext_Click(object sender, EventArgs e)
    {            
        this.TopMost = true;
        btnNext.Enabled = false;
        progressBar1.Step = 0;

        if (_bgwTimer.IsBusy)
            _bgwTimer.CancelAsync();
        else
            _bgwTimer.RunWorkerAsync();
    }

Upvotes: 1

Views: 4180

Answers (4)

Hans Passant
Hans Passant

Reputation: 941337

You forgot to start the worker. Add this line to your OnLoad() method:

   bgwTimer.RunWorkerAsync();

Upvotes: 2

Robert Harvey
Robert Harvey

Reputation: 180787

Put a breakpoint, or a Debug.Print or System.Windows.Forms.Messagebox just before bgwTimer.ReportProgress(i), to verify that you're actually entering the while loop.

Note that the BackgroundWorker is not actually a timer; it's a wrapper for a thread that provides a threadsafe invoking layer for your user interface.

Your if (bgwTimer.CancellationPending) { } should be inside the while loop, not outside it. It will only get checked once in your current code.

Note that, if you're inside the DoWork event handler, then by definition you're running an asynchronous process, so IsBusy should always be true (according to the MSDN documentation), and therefore your while is an infinite loop. But check it with your debugger.

Upvotes: 3

Mike Perrenoud
Mike Perrenoud

Reputation: 67898

It's not raising the event because the value of i is always zero, which is helpfully undocumented but I found out the same thing when building a background worker a while back.

Upvotes: 3

Tomtom
Tomtom

Reputation: 9394

In the DoWork-Method replace bgwTimer through ((BackgroundWorker)sender). Maybe this is the problem

Upvotes: 0

Related Questions