3

I've got one form called Sorter. There is the button 'jademy' on it which opens window 'Progress Window'

private void jademy_Click(object sender, EventArgs e)
{
    ProgressWindow progress = new ProgressWindow();
    progress.ShowDialog();
}

Code of 'Progress Window' form is following:

public partial class ProgressWindow : Form
{
    private BackgroundWorker backgroundWorker = new BackgroundWorker();

    public ProgressWindow()
    {
        InitializeComponent();
        stop.Visible = true;
        ok.Visible = false;
        backgroundWorker.RunWorkerAsync();
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.WorkerSupportsCancellation = true;

        #region block1

        backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
        backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
        backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

        #endregion
    }

    private void stop_Click(object sender, EventArgs e)
    {
        backgroundWorker.CancelAsync();
    }

    private void ok_Click(object sender, EventArgs e)
    {
        this.Close();
    }

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

    }

    private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        this.Text = "Done: " + e.ProgressPercentage.ToString() + "%";
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if ((e.Cancelled == true))
        {
            MessageBox.Show("Cancelled", "Message", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk);
        }

        else if (!(e.Error == null))
        {
            MessageBox.Show("Error: " + e.Error.Message, "ERROR!", MessageBoxButtons.OKCancel);
        }
        else
        {
            ok.Visible = true;
            stop.Visible = false;
        }
    }
}

Now. I have three problems.

  1. Click on stop button does nothing. It seems that 'backgroundWorker.CancelAsync()' doesn't stop the process.

  2. When I close progress window and I want to run it again I have to wait some time before click on 'jademy' button. Otherwise progress window is displayed like this: enter image description here (and nothing changes) instead of this: enter image description here It looks like the program "remembers" that work was done even though it is a new instance of ProgressWindow. Notice that on the incorrect version 'OK' button is visible at once - instead of waiting for the completion of the work.

  3. I would like to clarify the code in "block 1". To be honest I don't understand it fully. Is this part really essential or not? I mean, I've found a lot of examples (also on this forum - e.g. here), where this part wasn't included and users were reporting that the solution works. In my case, without this part progress bar didn't work at all, but maybe I've done something wrong.

Community
  • 1
  • 1
Piotrek
  • 169
  • 3
  • 17

3 Answers3

2
  1. Calling CancelAsync stops any pending work. But if the work has already started, the method body needs to check if cancel was called. See CancelAsync

CancelAsync submits a request to terminate the pending background operation and sets the CancellationPending property to true.

When you call CancelAsync, your worker method has an opportunity to stop its execution and exit. The worker code should periodically check the CancellationPending property to see if it has been set to true.

  1. I have no idea about it. By the way the images do not work. Embed it in the question.
  2. The code assigns a method that is executed when the BackgroundWorker starts and you hook up methods to report the progress and do cleanup / updates once the background work is complete.
Ganesh R.
  • 4,337
  • 3
  • 30
  • 46
1

BackgroundWorker.CancelAsync is often misunderstood. It does not stop any pending work but is merely a signal to the UI thread that the work has been canceled! It just sets the CancellationPending property, which you can poll in the DoWork regularly.

Unfortunately the MSDN example with the Thread.Sleep calls in the DoWork is a very silly one. Normally you call a blocking operation in DoWork, which is often completely UI-independent.

See my answer here for a more usable example.

Community
  • 1
  • 1
György Kőszeg
  • 17,093
  • 6
  • 37
  • 65
1

1. According to MSDN BackgroundWorker Class page, maybe you should add a break to the loop.

    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);
            }
        }
    }

2. Have no idea.

3. The block 1 region is setting for BackgroundWorker event. In my case , it normally will appear at Form1.Designer.cs if I click the lightning icon in attribute to set the event.

Bryant.C
  • 11
  • 2