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

*Required
*Required (Never published)