Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronizing a timer to prevent overlap

I'm writing a Windows service that runs a variable length activity at intervals (a database scan and update). I need this task to run frequently, but the code to handle isn't safe to run multiple times concurrently.

How can I most simply set up a timer to run the task every 30 seconds while never overlapping executions? (I'm assuming System.Threading.Timer is the correct timer for this job, but could be mistaken).

like image 852
JoshRivers Avatar asked Sep 04 '25 16:09

JoshRivers


2 Answers

You could do it with a Timer, but you would need to have some form of locking on your database scan and update. A simple lock to synchronize may be enough to prevent multiple runs from occurring.

That being said, it might be better to start a timer AFTER your operation is complete, and just use it one time, then stop it. Restart it after your next operation. This would give you 30 seconds (or N seconds) between events, with no chance of overlaps, and no locking.

Example :

System.Threading.Timer timer = null;

timer = new System.Threading.Timer((g) =>
  {
      Console.WriteLine(1); //do whatever

      timer.Change(5000, Timeout.Infinite);
  }, null, 0, Timeout.Infinite);

Work immediately .....Finish...wait 5 sec....Work immediately .....Finish...wait 5 sec....

like image 142
Reed Copsey Avatar answered Sep 07 '25 09:09

Reed Copsey


I'd use Monitor.TryEnter in your elapsed code:

if (Monitor.TryEnter(lockobj))
{
  try
  {
    // we got the lock, do your work
  }
  finally
  {
     Monitor.Exit(lockobj);
  }
}
else
{
  // another elapsed has the lock
}
like image 29
jsw Avatar answered Sep 07 '25 10:09

jsw