Time limiting a method in C# Time limiting a method in C# multithreading multithreading

Time limiting a method in C#


Unfortunately there is no 100% safe way to terminate a thread cleanly, as you seem to want.

There are many ways you can try to do it though, but they all have some sideeffects and downsides that you might want to consider.

The only clean, safe, and approved, way to do this is to get the cooperation of the thread in question and ask it nicely. However, this is only a 100% guaranteed way if you're in control of the code. Since you're not, it won't be.

Here's the problem.

  • If you do a Thread.Abort, you risk leaving the appdomain in an unsafe state. There could be files left open, network or database connections left open, kernel objects left in an invalid state, etc.
  • Even if you place the thread into its own appdomain, and tear down the appdomain after aborting the thread, you can't be 100% safe that your process won't have problems in the future because of it.

Let's look at why cooperation isn't going to be 100% either.

Let's say the thread in question often needs to call into your library code, in order to draw on screen, or whatnot. You could easily place a check into those methods, and throw an exception.

However, that exception could be caught, and swallowed.

Or the code in question could go into an infinite loop that doesn't call your library code at all, which leaves you back to square one, how to cleanly kill the thread without its cooperation.

Which I already said you can't.

There is, however, one method that might work. You could spawn the bot into its own process, then kill the process when it times out. This would give you a higher chance of success because at least the operating system will take care of all resources it manages when the process dies. You can of course have the process leave corrupted files on the system, so again, it's not 100% clean.

Here's a blog entry by Joe Duffy that explains a lot about these problems: Managed code and asynchronous exception hardening.


A .NET 4.0 Task gives you considerably flexibility with regard to cancelling.

Run the delegate in a Task that you've passed a CancelationToken into, like this.

There's a fuller example here.

edit

In light of the feedback, I believe that the right answer is to follow this plan:

  1. Limit the AI using CAS, so that it can't access threading primitives or mess with files.

  2. Give it a heartbeat callback that it is morally obligated to call from inside long loops. This callback will throw an exception if the thread has taken too long.

  3. If the AI times out, log a weak move for it, and give it a short amount of time to call that callback. If it doesn't, just put the thread to sleep until its next turn. If it never does snap out of it, it will keep logging weak moves until the process kills it for being a background thread.

  4. Profit!


One option is certainly to spin up a new Thread yourself, rather than relying on BeginInvoke. You can implement the timeout via Thread.Join and (unceremoniously) kill the thread, if necessary, via Thread.Abort.