0

I have the same problem as described in this topic How to let Timer skip tick if the previous thread is still busy

I don't know if I should create new topic for my problem, or I can "up" somehow existent thread (please let me know if i'm wrong creating new topic)

I wrote such solution:

Mutex refreshMutex = new Mutex();
void OnRefreshTimedEvent(object source, ElapsedEventArgs args)
{
    try
    {
        refreshMutex.WaitOne();
        // do work
    } finally
    {
        refreshMutex.ReleaseMutex();
    }
}

I think it's better because it's thread-safe and doesn't lock entiry object. I would appreciate any comments cause I'm pretty novice in C# :)

Does anyone see any potential problems with what I've shared? I can't ask as an answer on the other discussion.

upd Well it seems solution above doesn't work (thanks to user24601 for noticing). But I don't like the answer from referenced question because the call to serviceTimer.Stop() is not thread-safe. It could be a problem in the extreme frequent timers theoretically (and probably practically), especially if system is used intensively (100% CPU load etc.). I'm thinking now about such pattern:

[MethodImpl(MethodImplOptions.Synchronized)]
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    try
    {
      serviceTimer.Stop(); 
      // do some heavy processing... 
    }
    finally
    {
      serviceTimer.Start(); 
    }
}
Community
  • 1
  • 1
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • Apart from locking, is there any reason why the timer stop/start answer provided on the linked question is inadequate? – Reddog Apr 25 '11 at 21:41
  • well locking is pretty serious issue as I understand. Also theoretically another thread can start the method while first thread executing serviceTimer.Stop(); (not sure if this is possible in practice) – Oleg Vazhnev Apr 25 '11 at 21:52
  • I've edited your question to make it less of an answer to the other question and more of a new question inspired by another. – Tim Post Apr 25 '11 at 22:12
  • Well my answer was deleted but at least I get a shout out! – DanTheMan Apr 26 '11 at 02:15
  • Hey, mods, why WAS my answer deleted? That's annoying. – DanTheMan Apr 26 '11 at 02:20

2 Answers2

2

This does not actually solve the problem. The Elapsed event is raised on a threadpool thread. When there are a lot of active TP threads in your app, the thread that calls your Elapsed event handler may take several seconds to start running. In fact, several of them may be scheduled while this delay takes place. Stopping the timer does not prevent these delayed threads from running. You can still have more than one thread calling your Elapsed event handler concurrently.

Set the timer's AutoReset property to False. Call the timer's Start() method in the finally block of your Elapsed event handler to get it going again. Or use a System.Threading.Timer with a period of 0. That's an all-around better timer, it doesn't swallow exceptions without a diagnostic either, like System.Timers.Timer does.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

Perhaps I'm missing something, but why don't you just disable AutoReset on the timer (assuming you're using System.Timers.Timer- you didn't specify)? Put a try/finally around your Elapsed handler impl to ensure that Start() always gets called when it's done. This way, your timer won't start again until the Elapsed handler has completed.

nitzmahone
  • 13,720
  • 2
  • 36
  • 39