Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force thread stop in .NET Core

Let's say i have .NET Core 2.0/2.1 program. There is a thread executing the following method. I want to stop it forcefully.

Important notes:

Cooperative multitasking (for example, with CancellationToken) is a good thing, but not the case

XY problem (https://en.wikipedia.org/wiki/XY_problem) does exist, but i just want to know if stopping this thread is actually possible

while (true)
{
    var i = 0;
    try
    {
        Console.WriteLine($"Still alive {i++}");
    }
    catch (Exception e)
    {
        Console.WriteLine($"Caught {e.GetType().Name}");
    }
}

Tried several options:

  • Thread.Abort - throws PlatformNotSupportedException, not an option
  • Thread.Interrupt - only works for threads in WaitSleepJoin state, which is not the case
  • Calling native API methods such as TerminateThread from kernel32.dll on Windows. This approach has a lot of problems like non-released locks (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686717(v=vs.85).aspx)

Concerns, from most important to least:

  • Releasing locks
  • Disposing objects in using directives
  • Actually collecting allocated objects

(as a corner case we can assume that out thread does not perform any heap allocations at all)

like image 735
Владимир Тырин Avatar asked Sep 05 '26 20:09

Владимир Тырин


1 Answers

Use a ManualResetEventSlim. The instance will need to be available to both the thread you are trying to stop and the thread which will cause the stop.

In your while(true) loop, do something like this:

var shouldTerminate = mres.Wait(100);
if (shouldTerminate) { break; }

What this does is wait until the ManualResetEvent is put into a Set state, or 100ms, whichever comes first. The value returned indicates if the event is Set or Unset. You'll start off with the MRE in an Unset state, and when the control thread wishes to terminate the worker thread, it will call the Set method, and then it can Join the worker thread to wait for it to finish. This is important as in your loop you could perhaps be waiting on a network call to finish, and the worker won't actually terminate until you are back at the top of the loop again. If you need to, you could check the MRE with Wait at multiple points in the worker thread to prevent further expensive operations from continuing.

like image 186
Andy Avatar answered Sep 07 '26 10:09

Andy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!