views:

115

answers:

3

I have a need to add a timeout to a long running thread. We're having some external issues which can sometimes cause that thread to hang at a certain line of code indefinitely. To make our process more robust, we would like to detect that the thread is no longer actively running/polling and abort the thread. This would let us clean up the resources and restart the thread.

What would be the preferred method of adding this functionality?

+2  A: 

You need two things:

  1. Some other thread that can do the monitoring and abort (your "monitor" thread)
  2. Some mechanism to see if the suspect thread is still working

In the simplest version your suspect thread updates a shared static variable with the current time with a reliable frequency. How that fits into the control flow of your thread is up to you (This is the hard part - you would normally do that sort of thing with, ahem, another thread). Then just have a second thread wake up and check it every so often. If it's not a recent time, abort the thread.

//suspect thread
foreach(var thing in whatever)
{
    //do some stuff
    SomeClass.StaticVariable = DateTime.Now;
}

//monitor thread
while(shouldStillBeWorking)
{
    Thread.Sleep(TimeSpan.FromMinutes(10));
    if (DateTime.Now.Subtract(TimeSpan.FromMinutes(15) < SomeClass.StaticVariable)
        suspectThread.Abort()
}
Isaac Cambron
This is in-line with how I wanted to approach the problem. Good to see it validated by someone else. While I can appreciate Eric's response, it's simply not the right fit for my specific application. Thanks guys!
Joel Martinez
+5  A: 

The preferred method is to run the unreliable subsystem in its own process, not its own thread. That way when it behaves badly you can destroy the entire process and have the operating system clean up whatever horrid mess it leaves behind. Killing a thread that is running unreliable code in your process can have all kinds of nasty side effects on your code because the operating system has no way of knowing what resources belong to the ill-behaved thread and which ones you're still using.

Long story short: do not share a process with code you cannot control.

Eric Lippert
This isn't really feasible for me because I need to get a result back from this process (it's the IBM MQSeries client). So that would make this separate process unwieldy to get data back to my application.
Joel Martinez
@Joel: then you have to decide what you prefer: robust and unwieldy, or fragile and easy. Design is of course the art of making compromises that best serve your customers and stakeholders; do your customers and stakeholders value robustness of the product higher or lower than the ease of writing the product?
Eric Lippert
+1 for separate processes, despite my answer. @Joel, why wouldn't you just have the last poll communicate the result to your monitor process (before ending the process)? For interprocess communication, I'm assuming you'd be using XML-RPC or something. Make the suspect process the "slave".
Isaac Cambron
A: 

Start a timer in your main app that aborts the worker thread after your timeout period elapses. Use a callback method from your worker thread to reset the timer.

ebpower