开发者

One another way to let Timer skip tick if the previous thread is still busy

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(obj开发者_JAVA百科ect sender, ElapsedEventArgs e)
{
    try
    {
      serviceTimer.Stop(); 
      // do some heavy processing... 
    }
    finally
    {
      serviceTimer.Start(); 
    }
}


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜