I need a time-out!

I need a time-out! Or more specifically, my methods need a time-out mechanism. And because I spent seven projects and quite some time on the web trying to find out how to do it correctly, I am writing this small article about the works.

A method with time-out capabilities will perform the action the user wants until a specific time has elapsed, then an error is returned. There are a few ways to implement it, the first method that I tried is the following:

  • Start a timer that will callback 1 time after x milliseconds
  • Start the work that needs to be done
  • Check if the timer has called it's callback method
  • Throw exception if timer did
  • Return normally

This idea is plane wrong. The method will first wait for the work to complete and next verify the elapsed time. This way we have gained no time at all. We need to rework this schema:

MainMethod:

  • Start a timer that will callback 1 time after x milliseconds
  • Start the work
  • Return normally

TimerCallback:

  • Throw exception

Ok, let's try this one. The idea is getting better, but there is still a problem. The callback method of the timer is handled by a thread in the ThreadPool . When an exception is thrown inside that thread, there is no way to handle it correctly in the main thread where the method with time-out is functioning. When the exception is thrown an uncaught exception occurs, not very user friendly. Again a rework:

MainMethod:

  • Start a delegate to do the requested work
  • Wait for x milliseconds for the delegate to finish
  • Throw exception when delegate not finished
  • Return normally

Delegate method:

  • Start the work that needs to be done

Now we're getting somewhere, the exception is thrown in the main method and the work is done separately. The last thing that's needed is a translation into code.

delegate object WorkDelegate(string arg);
public object DoWork(string arg)
{       
    WorkDelegate d = new WorkDelegate(DoWorkHandler);
    IAsyncResult res = d.BeginInvoke(arg,null,null);
    if(res.IsCompleted == false)
    {
        res.AsyncWaitHandle.WaitOne(10000,false);
        if(res.IsCompleted == false)
            throw new ApplicationException("Timeout");
    }
    return d.EndInvoke((AsyncResult)res);
}
private object DoWorkHandler(string arg)
{
    Thread.Sleep(5000);
    return "blah " + arg;
}

Here's the breakdown. The public method is the one called by the user of the class. It will first create a delegate to do the actual work. The undocumented BeginInvoke method is called to start the work asynchronously. Next a check is made to see if the delegate has finished already, if not we wait and check again. Using the now obtained info it is possible to either throw an exception, or to return normally using the, again undocumented, EndInvoke method. Quite simple, isn't it?

To try it all out I included a test application, fiddle around with the wait time in the delegate method and the main method to see it all working.

You might also like...

Comments

Wouter van Vugt

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“You can stand on the shoulders of giants OR a big enough pile of dwarfs, works either way.”