0

I am working on a c# app. I want to use a background worker to make all my heavy processing, but I'd like to be able to stop it while running. The problem I face is that I can cancel it with "backgroundWorker1.CancelAsync()" but it doesn't stop right away.

Is there any way to instantly "kill" the thread ? Is it possible to stop the thread instantly after clicking instead of waiting the end of the current sleep ?

My code :

    private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        for (int i = 1; i <= 10; i++)
        {
            if (backgroundWorker1.CancellationPending == true)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                System.Threading.Thread.Sleep(5000);
                backgroundWorker1.ReportProgress(i * 10);
            }
        }
    }

    private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        string prog = (e.ProgressPercentage.ToString() + "%");
        Console.WriteLine(prog);
    }

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

    private void button27_Click(object sender, EventArgs e)
    {
        Console.WriteLine(backgroundWorker1.IsBusy.ToString());
    }

Thanks to anyone who helps me ^^

  • 3
    The reason we have cancellation tokens and cooperative cancellation is because we've learnt the lessons of bad APIs such as `Thread.Abort` - that is, if you *know* that the other thread is in a safe position for it to be terminated, you can surely insert a check for the cancellation token at that point. And if you *don't* know it's in a safe position... – Damien_The_Unbeliever Feb 10 '21 at 14:07
  • 4
    Try using `Task.Delay` with cancellation instead of `Thread.Sleep`. – Dusan Feb 10 '21 at 14:08
  • There is only one way to kill a thread: by calling the [Thread.Abort](https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-5.0) method. However, starting with .NET 5 it is no longer supported. So give up your dreams of hard breaking the thread. – Alexander Petrov Feb 10 '21 at 14:37
  • Okay. Thank you for your answers. I will try to find a convenient and conventional way to do. – Vincent Clavel Feb 10 '21 at 14:49

1 Answers1

3

Cancelling background work needs to be done cooperatively. The alternative would be equivalent to thread.Abort, and that is a bad idea for all the reasons listed in this answer.

The correct approach would be to increase the frequency the cancellation is checked. Or if you are waiting for IO, use a IO-method that accepts a cancellation token. I assume your example with thread.sleep is for demonstration purposes only, otherwise you could simply replace it with Task.Delay(5000, CancellationToken).

Also, it is not necessarily terrible if a background task lives a short while after it is cancelled, as long as it is guaranteed to eventually complete without side effects.

Note that while background worker provides things like progress, the more modern way is to use tasks, async/await and cancellationToken.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Indeed the thread.sleep is there for the example. In reality it is replaced with a c++ call that takes quite a while to be done so I can't add intermediate cancellation check. Thank you for your answer. Thanks to you I understand a bit better all the problems linked to thread cancellation and abortion :) – Vincent Clavel Feb 10 '21 at 16:08