-1

I am coding an application that starts and stops a thread by a command. If client receives "start" it starts the thread, and if client receives "stop" -- it stops. My concern is in thread-safety in my code and the proper practice for this problem. My code:

Thread thread = new Thread(doStuff);
... 
//wait for the commands
if(command.Equals("start")
{
   thread.Start();
}
if(command.Equals("stop")
{
   //this code won't work of course
   thread.Abort();
}
public static void doStuff()
{
    while(true)
    {
        //do stuff
    }
}

The problem is that abort will not work, because it does not know if it was even started. Also, i need to somehow know if the thread is actually alive.. Maybe I need to wrap it around abort statement and check thread.isAlive status

But what I tried to do is to create a common variable for the function.

bool running = true;
Thread thread = new Thread(doStuff);
... 
//wait for the commands
if(command.Equals("start")
{
   thread.Start();
}
if(command.Equals("stop")
{
   //this code won't work of course
   running = false;
}
public void doStuff()
{
    while(running)
    {
        //do stuff
    }
}

This implementation is horrible and causes a crash sometimes within 15 seconds. Could someone please show me an appropriate way to achieve my goal? Thank you

Dan
  • 1
  • 5
    The bigger problem is that you should never call `thread.Abort()`. –  May 07 '21 at 23:49
  • You may find this interesting: [What's wrong with using Thread.Abort()](https://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread-abort) – Theodor Zoulias May 08 '21 at 00:42
  • 'I am coding an application that starts and stops a thread by a command'....you have lost already. – Martin James May 08 '21 at 20:22

1 Answers1

3

You cannot call Thread.Abort() safely or at all - depending on your version of the framework.

The way to do this safely is to have co-operative cancellation.

Here's how:

public static void doStuff(CancellationToken ct)
{
    while (true)
    {
        //do stuff
        if (ct.IsCancellationRequested)
        {
            return;
        }
    }
}

And then call it like this:

var cts = new CancellationTokenSource();

Thread thread = new Thread(() => doStuff(cts.Token));

//wait for the commands
if (command.Equals("start")
{
    thread.Start();
}
if (command.Equals("stop")
{
    cts.Cancel();
}

Do note that the CancellationTokenSource is disposable so it should be disposed when it has been finished with.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172