0

I have a WinForm application that when I press on "Build" it starts a function in a different thread:

Thread m_SearchingThread;
private void buttonBuild_Click(object sender, EventArgs e)
{
    Engine.BuildRPCDBStatusUpdate += Engine_BuildDBStatusUpdate;
    // Saves the thread as class member
    Thread m_SearchingThread = new Thread( o => Engine.BuildDataBase(textBoxFolderForSearch.Text));
    m_SearchingThread.Start();
}

While the function is still running, I have other button named "Stop" and when I press on it, it should stop the thread functionality:

private void buttonStop_Click(object sender, EventArgs e)
{
    if (m_SearchingThread != null)
    {
        m_SearchingThread.Abort();
    }
}

But after I pressed the "Stop" button, the member m_SearchingThread is null and thread is still running.
How can it be?
I debugged it and saw that when I assign new thread to m_SearchingThread, it is not null.

EDIT:
I tried to cancel it with CancellationToken without success:

CancellationTokenSource cts = new CancellationTokenSource();
private void buttonBuild_Click(object sender, EventArgs e)
{
    ...
    ThreadPool.QueueUserWorkItem(s =>
    {
        CancellationToken token = (CancellationToken)s;
        if (token.IsCancellationRequested)
            return;
        Engine.BuildDataBase(textBoxFolderForSearch.Text);
        token.WaitHandle.WaitOne(1000);
    }, cts.Token);
}

private void buttonStop_Click(object sender, EventArgs e)
{
    cts.Cancel();
}
E235
  • 11,560
  • 24
  • 91
  • 141
  • 3
    [**Never** call `Thread.Abort()`](https://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread-abort) - to cancel an operation you need to support `CancellationToken`. Killing threads using `Thread.Abort()` (generally) will put your program into an undefined state and cause corruption. – Dai Mar 15 '22 at 16:57
  • See my edit, I tried with `CancellationToken`, the `cts.Cancel()` doesn't stop the thread. It is still running. – E235 Mar 15 '22 at 17:03
  • 2
    You're not assigning the field, you're creating a local variable with the same name. I'd also suggest using `Task` rather than creating threads. – Charles Mager Mar 15 '22 at 17:03
  • @CharlesMager I created `CancellationTokenSource cts = new CancellationTokenSource();` outside the function -> it is a class member. Same as with the `m_SearchingThread` – E235 Mar 15 '22 at 17:05
  • 1
    It's not the same - you don't attempt to assign it within a method. Your cancellation approach isn't working because nothing is checking the token for cancellation once the work starts. You'd need to pass the token to `BuildDataBase` and return early at a suitable point if cancelled. It doesn't just magically abort. – Charles Mager Mar 15 '22 at 17:09
  • @E235 - Calling `cts.Cancel()` doesn't cancel the thread, it just signals that the thread should cancel. The thread itself needs to shut itself down when cancelled. `.Abort()` is dangerous and should not be used. – Enigmativity Mar 16 '22 at 01:40

1 Answers1

3

You are setting the local variable m_SearchingThread instead the outside variable m_SearchingThread. You have two different variables. Remove "Thread" in "Thread m_SearchingThread = new Thread..."

Thread m_SearchingThread;
private void buttonBuild_Click(object sender, EventArgs e)
{
    Engine.BuildRPCDBStatusUpdate += Engine_BuildDBStatusUpdate;
    // Saves the thread as class member
    /*Thread */m_SearchingThread = new Thread( o => Engine.BuildDataBase(textBoxFolderForSearch.Text));
    m_SearchingThread.Start();
}
Victor
  • 2,313
  • 2
  • 5
  • 13