Geeks With Blogs
Alex's Blog-o-monium

There’re frequent times when I need to perform some sort of periodic tasks within the application: refresh in-memory shared data from the backend, status checks, emitting a health beat (pulse) with some sort of statistics to a log or UDP broadcast, and so on.

As a bonus, it’d be nice if such tasks were to be non-blocking and thread-safe.

Since, the calls should be to non-blocking, asynchronous processes – they will require a separate thread to run on, in order to avoid interfering with the main process. So, how can we launch such thread?

We can invoke a new thread to a method call where the thread will run inside a “while” loop with a Thread.Sleep call at the end each iteration. We’d need to start such thread before all else (maybe in the constructor of the enveloping class), and than forget all about it.

Of course, nothing else would have much use for such method as it’s stuck in an infinite loop. And some may suggest that using infinite loops in your domain logic is a bad idea to begin with. I’d also point out that this can potentially cause potential run-away processing and thread-safety concerns. So, what’s to be done?

I find use of TimerCallback (http://tinyurl.com/c5grkcd) delegate a more elegant approach. Such delegated method would execute in a system thread pool separate from the thread which instantiated the callback. And, if need be, it can be aborted with a Timer.Change call.

We can start with declaring and instantiating some basic players in all this:

  1. private readonly static AutoResetEvent _autoEvent = new AutoResetEvent(false);
  2. private static TimerCallback _tcb = MyPeriodicMethod;
  3. private static Timer _stateTimer = new Timer(_tcb, _autoEvent, dueTime: 0, period: 60000);

‘MyPeriodicMethod’ refers to the target method. and ‘period: ‘ is set to 60000 milliseconds (1 minute) – i.e. target method will be called every minute.

 

Moving onto the target method:

  1. private static DateTime _lastRunDatetime;
  2. /// <summary>
  3. /// Target method for the TimerCallback
  4. /// </summary>
  5. /// <param name="stateInfo">The state info.</param>
  6. [MethodImpl(MethodImplOptions.Synchronized)]
  7. private static void MyPeriodicMethod(Object stateInfo)
  8. {
  9.     if (DateTime.Now.Subtract(_lastRunDatetime).TotalMilliseconds < 60000)
  10.         return;
  11.  
  12.     var autoEvent = (AutoResetEvent)stateInfo;
  13.  
  14.     try
  15.     {
  16.         _synRoot.EnterReadLock();
  17.  
  18.         /* do all the "periodic" work here */
  19.  
  20.     }
  21.     catch (Exception ex)
  22.     {
  23.         /* handle exception */
  24.     }
  25.     finally
  26.     {
  27.         if (_synRoot.IsReadLockHeld)
  28.             _synRoot.ExitReadLock();
  29.  
  30.         _lastRunDatetime = DateTime.Now;
  31.     }
  32. }

 

Couple things of note here. Notice [MethodImpl(MethodImplOptions.Synchronized)] (line 6) method attribute. What this means is that only one thread at a time can call this method.

If for some reason two or more timer-calls run into each other, i.e. call from interval 1 is still running when call from interval 2 comes in – the call from interval 2 will wait for the first one to complete.

Also, notice the _lastRunDateTime variable (line 1). This keeps track of the last time the method was called. So, if there’s a prematurely arriving thread – we can short-circuit and force it back out of execution (line 10); if not, than the code is executed (inside a thread-safe critical section) and the _lastRunDateTime is updated (line 30).

C'est fini! Merci!

Posted on Monday, August 20, 2012 12:01 PM | Back to top

Copyright © Strenium | Powered by: GeeksWithBlogs.net