简体   繁体   中英

Stopping background worker

My app uses background worker to go do some work inside a loop. I have it so that at each loop iteration, it checks if cancellation pending is true and if it is, breaks out the loop. All OK, my app stops processing once it is finished the current iteration of the loop. The problem is that I think the background worker is still running - if I click the button to start processing again, I get an error saying the background worker is busy.

I was going to dispose of the worker but then it is created when the form runs and so if I dispose of it, it is not there to start doing work again. What I really want to do is tell the background worker that it is complete, if I click a 'stop processing' button, so it is ready to start processing again when I click the start button!

I was going to try this:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while (!backgroundWorker1.CancellationPending) 
    {
        // Start processing in a background thread so the GUI remains responsive,
        // pass in the name of the text file produced by 
        // PFDR FilenameLogic(txtLetterType.Text); 
    } 
}

When you create the worker, set worker.WorkerSupportsCancellation to true . Now inside the DoWork handler, you must periodically (most commonly, at the start of some loop, etc) check for worker.CancellationPending - if it is true, set e.Cancel = true; (so that you can distinguish completion from cancellation), clean-up, and exit ( return; ). Now your cancel button can invoke worker.CancelAsync(); and it will act appropriately.

Same answer as Marc Gravell but you don't seem to follow.

Are you setting e.cancel = true?

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

I hardly found a nice way how to cancel a Backgroundworker over a Stop Button :

My App looks like this, two buttons and one progressbar:

在此输入图像描述

After pressed Stop Button it looks like this:

在此输入图像描述

For the Start button click method, the code checks if the BGW is busy. If not Start the BGW:

private void btnStart_Click(object sender, EventArgs e)
    {


        //BGW
        if (!backgroundWorker1.IsBusy)
        {

            backgroundWorker1.RunWorkerAsync();

        }



    }

The stop button calls the following method, which sets a flag, CancellationPending to true:

        private void btnStop_Click(object sender, EventArgs e)
    {
        backgroundWorker1.CancelAsync();
    }

This flag can be used in the backgroundWorker1 _DoWork method, which is responsible for processing high time consuming functions:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i <= 100; i++)
        {

            backgroundWorker1.ReportProgress(i);
            Thread.Sleep(100);



            if (backgroundWorker1.CancellationPending && backgroundWorker1.IsBusy)
            {
                e.Cancel = true;
                return;
            }
        }
    }

And now comes the tricky part, because before closing the extra thread, you have to check the e object in the backgroundWorker1 _ProgressChanged if it is cancelled or not!!!!! OTHERWISE you will get an Error .

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        int i = 0;

        if (!e.Cancelled)
        {
            i = (int)(e.Result);
        }
        else
        {
            i = 0;
        }

        // Check to see if an error occurred in the
        // background process.
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
            return;
        }

        // Check to see if the background process was cancelled.
        if (e.Cancelled)
        {
            MessageBox.Show("Processing cancelled.");
            return;
        }

        // Everything completed normally.
        // process the response using e.Result
        MessageBox.Show("Processing is complete.");

    }

Extra information: Dont forget to set these Backgroundworker flags:

            //Set WorkerReportsProgress true - otherwise no ProgressChanged active
        backgroundWorker1.WorkerReportsProgress = true;
        backgroundWorker1.WorkerSupportsCancellation = true;

If this tiny tutorial was helpful --> Thumb up

我似乎已经解决了错误 - 在Backgroundworker DoWork方法中,我放了一段时间取消不正确,当它是真的我设置e.Cancel = true它现在似乎工作正常!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM