How close BackgroundWorker thread when application is deactivated?

Aram Gevorgyan picture Aram Gevorgyan · Oct 1, 2011 · Viewed 9.8k times · Source

I create thread with BackgroundWorker, and in the loop I check every time if CancellationPending is true or not, like this:

   public MainPage()
    {
        InitializeComponent();

        bw = new BackgroundWorker();
        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    }

    private void ButtonStart_Click(object sender, RoutedEventArgs e)
    {
        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }
    }

    private void ButtonCancel_Click(object sender, RoutedEventArgs e)
    {
        if (bw.WorkerSupportsCancellation)
        {
            bw.CancelAsync();
        }
    }

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

        for (int i = 1; i <= 100; i++)
        {
            Debug.WriteLine("The tread is working");
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                bw.CancelAsync();
                break;
            }
            else
            {

                System.Threading.Thread.Sleep(500);
                worker.ReportProgress(i);
            }
        }
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            tbProgress.Text = "Canceled";
        }
        else if (e.Error != null)
        {
            tbProgress.Text = "Error: " + e.Error.Message;
        }
        else
        {
            tbProgress.Text = "Done";
        } 
    }

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        tbProgress.Text = e.ProgressPercentage.ToString() + "%";
    }

When application is deactivated, the thread wasn't closed, it is aborted and the exception occurs. How close threads with BackgroundWorker when application is deactivated?

Answer

PostalBatman picture PostalBatman · Nov 10, 2011

When an app is deactivated, every thread other than the main UI thread will throw a ThreadAbortException as soon as it becomes active. This appears to be "by design" as a way of forcing apps to quickly stop what they are doing. Threads can catch the ThreadAbortException and wrap up what they are doing, but be aware that the ThreadAbortException will be automatically raised again at the end of the catch block. Any code in a finally block will also be executed.

For your specific issue, there's no reason to attempt to cancel the BackgroundWorker when the app is deactivated because the ThreadAbortException will occur and will effectively stop the background worker. If you want to do something to clean up when this occurs, you catch the ThreadAbortException in bw_DoWork, do what you need to do, and then let it die.

To get it to start again after activation, you would have to restart the background worker, just like you did the first time the app ran.