3

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:

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)

  • 5
    What is wrong with changing `while(true)` to something you can control? – Theraot Jun 20 '18 at 21:14
  • 1
    Not supporting it, but just for information: https://stackoverflow.com/a/39247629/613130 . There is a "secret" thread abort (https://github.com/dotnet/coreclr/blob/master/tests/src/baseservices/threading/regressions/threadex.cs) – xanatos Jun 20 '18 at 21:15
  • @Theraot, it is possible to just take external assembly, find some method in it and execute on this dedicated thread. Yes, in general, this is a horrible solution. But let's say that this method is not malicious, just can contain bugs leading to infinite loops, which i want to stop in 1 second. – Владимир Тырин Jun 20 '18 at 21:17
  • 2
    If you cannot modify the source, then consider changing your architecture so that you can run this on an isolated process that you can kill (use interprocess communication as needed). Edit: if you are saying that you can modify the source, but it is not simple, you can add if statements that do a volatile read on a variable you control, and throw an exception. – Theraot Jun 20 '18 at 21:21
  • @ВладимирТырин - You need to know that there is nothing you can do to forcibly (the word isn't forcefully) stop a .NET thread without possible corrupting the run-time. You simply have to kill all threads or kill none. So doing this in a separate process is the only way. – Enigmativity Jun 20 '18 at 23:15

1 Answers1

0

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.

Andy
  • 8,432
  • 6
  • 38
  • 76