Reputation: 9285
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
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
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:
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