Ole Albers
Ole Albers

Reputation: 9285

Killing a Thread in C#

This is not about terminating a system-process but killing "myself". I have several parallel theads, which CAN hang because of different reasons.

I already created a watchdog when a thread is taking too long:

TimerCallback timerDelegate = new TimerCallback(CheckProcessStatus);
System.Threading.Timer watchDogTimer = new Timer(timerDelegate, new ProcessHealth(plog), 1000 * 60, 1000 * 60);
try
   {
   // lots of code here
   } finally
   {
      watchDogTimer.Dispose();
   }

Watchdog:

public void CheckProcessStatus(Object timerState) {
    ProcessHealth ph = (ProcessHealth)timerState;
    System.writeLine(string.Format("process runs for {0} minutes!", ph.WaitingTime);
    if (ph.WaitingTime>60) {
      // KILL THE PROCESS
    }
}

When "lots of code here" takes too long I want to terminate the thread no matter what state it is in. (at "Kill the process").

What would be the best approach?

Thread.CurrentThread.Interrupt()

OR

Thread.CurrentThread.Abort()?

Or are there even better approaches? (I cannot use "simple" mechanisms like boolean "stop"-variables as the "lots of code here" is VERY Dynamic calling other classes via reflection etc.

Does that even work? Or do I just kill the watchdog-thread, NOT the thread to be watched?

Upvotes: 2

Views: 4056

Answers (2)

Brian Gideon
Brian Gideon

Reputation: 48949

Thread.Abort attempts to terminate the target thread by injecting an out-of-band (asynchronous) exception. It is unsafe because the exception gets injected at unpredictable points in the execution sequence. This can (and often does) lead to some type of corruption in the application domain because of interrupted writes to data structures.

Thread.Interrupt causes most blocking calls in the BCL (like Thread.Sleep, WaitHandle.WaitOne, etc.) to bailout immediately. Unlike aborting a thread, interrupting a thread can be made completely safe because the exception is injected at predictable points in the execution sequence. A crafty programmer can make sure these points are considered "safe points".

So, if "lots of code here" will respond to Thread.Interrupt then that might be an acceptable approach to use. But, I would like to steer you more towards the cooperative cancellation pattern. Basically, this means your code must periodically poll for a cancellation request. The TPL already has a framework in place for doing this via CancellationToken. But, you could easily accomplish the same thing with a ManualResetEvent or a simple volatile bool variable.

Now, if "lots of code here" is not under your control or if the cooperative cancellation pattern will not work (perhaps because you are using a faulty 3rd party library) then you pretty much have no other choice but to spin up a completely separate process to run the risky code. Use WCF to communicate with the process and if it does not respond then you can kill it without corrupting the main process. It is a lot of work, but it may be your only option.

Upvotes: 3

usr
usr

Reputation: 171168

Aborting a thread, when it is in an unknown state, is not advisable. Say, the thread is currently executing a static constructor. The static ctor will be aborted and never run again (because faulting static ctor's never run again). You have effectively destroyed global state in your AppDomain without a way to ever recover.

There are lots of other hazards as well. That just doesn't fly.

There are two production-ready choices aborting threads:

  1. Cooperatively (set an event or a boolean flag in combination with Thread.MemoryBarrier)
  2. Don't abort the thread, but the entire AppDomain or process. Thread level granularity is too small. You need to delete all state related to that thread, doo.

I want to stress that you cannot make this work any other way. You will have the strangest faults in production if you insist on aborting threads non-cooperatively.

Upvotes: 3

Related Questions