I knocked together a solution similar to the one linked to, except that I used Thread.Interrupt() instead of Thread.Abort(), thinking that would be a little kinder to the main thread. The problem is that Thread.Interrupt() won't interrupt a call that is blocked, so it is unsatisfactory under many cases. Thread.Abort() is a dangerous call and should be avoided where possible. Pick your poison.
For what it's worth, this is my implementation:
public static class AbortableProc
{
public static void Execute(Action action, Action timeoutAction, int milli)
{
Thread currThread = Thread.CurrentThread;
object stoppedLock = new object();
bool stopped = false;
bool interrupted = false;
Thread timer = new Thread(() =>
{
Thread.Sleep(milli);
lock (stoppedLock)
{
if (!stopped)
{
currThread.Interrupt();
stopped = true;
interrupted = true;
}
}
});
timer.Start();
try
{
action();
lock (stoppedLock)
{
stopped = true;
}
}
catch (ThreadInterruptedException)
{
}
if (interrupted)
{
timeoutAction();
}
}
}
For grins, I put in a timeoutAction so that you could use it in this mode:
AbortableProc.Execute(
() => { Process(kStarting); Process(kWorking); Process(kCleaningUp); },
() => { if (IsWorking()) CleanUp(); }
};