Prevent multiple instance of a service - best approach? Prevent multiple instance of a service - best approach? windows windows

Prevent multiple instance of a service - best approach?


Make your timer a one-shot, and re-initialize it in the elapsed event handler. For example, if you're using System.Timers.Timer, you'd initialize it like this:

myTimer.Elapsed = timer1Elapsed;myTimer.Interval = 1000; // every secondmyTimer.AutoReset = false; // makes it fire only oncemyTimer.Enabled = true;

And your elapsed event handler:

void timerElapsed(object source, ElapsedEventArgs e){    // do whatever needs to be done    myTimer.Start(); // re-enables the timer}

The drawback to this is that the timer doesn't fire on one second intervals. Rather, it fires one second after the last tick's processing finishes.


Don't use a timer to spawn threads. Only ever start one thread. When the thread has finished a work cycle, calculate how long remains before the next cycle should start. If this interval is 0 or negative, loop back immediately and start a new cycle, if positive, sleep for that interval before looping back.

This is usually done by taking the int result of an unsigned int subtraction between the finish ticks and start ticks, so giving the elapsed ticks taken by the work. Subtracting this from the desired interval gives the new time remaining.

No extra timer thread needed, no possibility of two threads running simultaneously, simplified overall design, no continual create/start/terminate/destroy, no mallocs, no new(), no stack allocate/deallocate, no GC.

Other designs using timers, mutexes, semaphores, locks etc. are just over complex. Why bother trying to stop the extra threads with synchro if it's just plain easier and simpler to not make any extra threads?

Sometimes, using a timer instead of a sleep() loop is just a really bad idea. This sounds like one of those times.

public void doWorkEvery(int interval){    while (true)    {        uint startTicks;        int workTicks, remainingTicks;        startTicks = (uint)Environment.TickCount;        DoSomeWork();        workTicks=(int)((uint)Environment.TickCount-startTicks);        remainingTicks = interval - workTicks;        if (remainingTicks>0) Thread.Sleep(remainingTicks);    }}


Instead of lock you can use Monitor.TryEnter() to return if a callback is already being executed by another timer thread:

class Program{    static void Main(string[] args)    {        Timer t = new Timer(TimerCallback, null,0,2000);        Console.ReadKey();    }    static object timerLock = new object();    static void TimerCallback(object state)    {        int tid = Thread.CurrentThread.ManagedThreadId;        bool lockTaken = false;        try        {            lockTaken = Monitor.TryEnter(timerLock);            if (lockTaken)            {                Console.WriteLine("[{0:D02}]: Task started", tid);                Thread.Sleep(3000); // Do the work                 Console.WriteLine("[{0:D02}]: Task finished", tid);            }            else            {                Console.WriteLine("[{0:D02}]: Task is already running", tid);            }        }        finally        {            if (lockTaken) Monitor.Exit(timerLock);        }    }}