Canceling BackgroundWorker when app exits

What is the best way to exit gracefully when the user closes the form while a background worker is working.

I have tried putting cancelasync in formclosing event but i am getting exceptions on Application.DoEvents()


this is inside the calling function
while (bgwDownload.IsBusy && !bgwDownload.CancellationPending)
{
    Application.DoEvents();
}




this is inside my do work
for (int i = 0; i < chunks; i++)
{
    bytes_read = from_web.Read(buffer, 0, buffer.Length);
    to_file.Write(buffer, 0, bytes_read);
    sender.ReportProgress(i * 100 / chunks);
    if (sender.CancellationPending)
    {
        from_web.Close();
        to_file.Close();
        response.Close();
        e.Cancel = true;
        Thread.Sleep(100);
        return;
    }

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (bgwDownload.IsBusy)
    {
        bgwDownload.CancelAsync();
        //Allow a little time to get things done
        Thread.Sleep(100);
    }
}


}

thanks


Answer this question

Canceling BackgroundWorker when app exits

  • edukulla

    Use of DoEvents() is often a problem (as you are finding), and you should avoid it like the plague. It is deeply unfortunate that the MS documentation actually uses DoEvents() in some sample code for BackgroundWorker! Whoever wrote that sample should be slapped, hard.

    You also shouldn't need to sleep to wait for things to finish - that's potentially a problem.

    Here's some sample code that doesn't need to use DoEvents() and doesn't need to use a Sleep to wait for things to finish. (It uses a sleep in the DoWork(), but that is merely to simulate a slow process.)



    public partial class Form1: Form
    {
    public Form1()
    {
    InitializeComponent();
    this.backgroundWorker1.WorkerSupportsCancellation = true;
    this.backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
    this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
    this.backgroundWorker1.RunWorkerAsync();
    }

    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
    for (;;) // Simulate work.
    {
    System.Threading.Thread.Sleep(10000);

    if (this.backgroundWorker1.CancellationPending)
    break;
    }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    if (this.closePending)
    {
    this.closePending = false;
    this.Close();
    }
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
    if (!this.closePending && this.backgroundWorker1.IsBusy)
    {
    this.backgroundWorker1.CancelAsync();
    this.Cursor = Cursors.WaitCursor;
    e.Cancel = true;
    this.closePending = true;
    }
    }

    private bool closePending;
    }




  • Canceling BackgroundWorker when app exits