Dervall
Dervall

Reputation: 5744

Using Timers to create a single timeout frequently

I'm working with a timeout which is set to occur after a certain elapsed period, after which I would like to get a callback. Right now I am doing this using a Timer that when fired disposes of itself.

public class Timeouter
{
    public void CreateTimeout(int timeout, Action onTimeout)
    {
        Timer t = null;
        t = new Timer(_ =>
            {
                onTimeout();
                t.Dispose();
            }, new object(), timeout, Timeout.Infinite);    
    }
}

I'm a bit concerned regarding the resource use of this timer since it could potentially be called quite frequently and would thus setup a lot of timers to fire just once and dispose of themselves. Considering that the timer is an IDisposable it would indicate to me that it indeed uses some sort of expensive resource to accomplish its task.

Upvotes: 4

Views: 1286

Answers (4)

Hans Passant
Hans Passant

Reputation: 941645

Creating a cheap timer that can time many intervals is intuitively simple. You only need one timer. Set it up for the closest due time. When it ticks, fire the callback or event for every timer that was due. Then just repeat, looking again through the list of active timers for the next due time. If a timer changes its interval then just repeat the search again.

Something potentially expensive might happen in the callback. Best way to deal with that is to run that code on a threadpool thread.

That's extraordinarily frugal use of system resources, just one timer and the cheapest possible threads. You pay for that with a little overhead whenever a timer's state changes, O(n) complexity to look through the list of active timers, you can make most of it O(log(n)) with a SortedList. But the Oh is very small.

You can easily write that code yourself.

But you don't have to, System.Timers.Timer already works that way. Don't help.

Upvotes: 1

Marcelo De Zen
Marcelo De Zen

Reputation: 9497

.Net has 2 or 3 timer classes which are expensive. However the System.Threading.Timer class which you're using is a very cheap one. This class do not use kernel resources or put a thread to sleep waiting for timeout. Instead it uses only one thread for all Timer instances, so you can easily have thousands of timers and still get a tiny processor and memory footprint. You must call Dispose only because you must notify the system to stop tracking some timer instance, but this do not implies that this is a expensive class/task at all. Once the timeout is reached this class will schedule the callback to be executed by a ThreadPool thread, so it do not start a new thread or something like this.

Upvotes: 1

James
James

Reputation: 9985

one other option is to maintain a sorted list of things which will timeout, add them to the list with their expiry time instead of their duration, keep the list sorted by the expiry time and then just pop the first item off the list when it expires.

You will of course need to most of this on a secondary thread and invoke your callbacks. You don't actaully need to keep the thread spinning either, you could set a wait handle on the add method with a timeout set for (a bit less than) the duration until the next timeout is due. See here for more information on waiting with a timeout.

I don't know if this would be better than creating lots of timers.

Upvotes: 1

Furqan Hameedi
Furqan Hameedi

Reputation: 4400

Though its not an answer, but due to length I added it as answer.

In a server/Client environment, AFAIK using Timers on server is not the best approach, rather if you have thick clients or even thin clients, you should devise some polling mechanism on client if it wants a certain operation to be performed on the server for itself(Since a client can potentially disconnect after setting up a timer and then reinstantiate and set a timer again an so on, causing your server to be unavailable at sometime in future(a potential DOS attack)),

or else think of a single timer strategy to deal with all clients, which implements sliding expirations or client specific strategies to deal with it.

Upvotes: 1

Related Questions