With.Timeout
So Tim Erickson and I have been going round and round on Twitter about how to add a generic Timeout mechanism to procedure calls.
Tim wants to wrap a using block in some sort of dark CLR magicks involving things I’ll probably never understand. I’m much less clever, so I opted for stealing the crap out of Oren’s syntax for his fabulous With.* stuff in Rhino.Commons.
This is what I ended up with:
public class With { public static void Timeout(Action action, int timeoutInMilliseconds) { var latch = new AutoResetEvent(false); var asyncResult = action.BeginInvoke(ar => latch.Set(), null); latch.WaitOne(timeoutInMilliseconds, false); if (!asyncResult.IsCompleted) { throw new TimeoutException("The specified Action has timed out."); } action.EndInvoke(asyncResult); } }
And tests/examples:
[TestFixture] public class WithTimeoutTests { [Test] public void ShouldPerformAction() { var actionWasPerformed = false; With.Timeout(() => actionWasPerformed = true, int.MaxValue); Assert.That(actionWasPerformed, "Action Was Not Performed."); } [Test] [ExpectedException(typeof(TimeoutException))] public void ShouldTimeoutLongOperation() { With.Timeout(() => Thread.Sleep(int.MaxValue), 1); } [Test] [ExpectedException(typeof(Exception))] public void ShouldPassThruThrownExceptionsFromAction() { With.Timeout(delegate { throw new Exception("Test"); }, int.MaxValue); } [Test] public void StupidUselessTest() { var timeout = 100; for (int i = 0; i < 100; i++) { try { With.Timeout(() => Thread.Sleep(timeout), timeout); Console.WriteLine(i + " Did Not Timeout"); } catch (TimeoutException e) { Console.WriteLine(i + " Timed out"); } } } }
I’m anxious to see Tim’s solution. I’ve gotten a lot more used to it, but the anonymous delegate/lambda syntax in C# still bugs the crap out of me.
Post a Comment