c#单线程计时器

pro*_*ach 6 c# multithreading timer

我想要一个具有以下属性的计时器:

  1. 无论启动多少次调用,只有一个回调线程正在运行

  2. 关于间隔,忽略了在回调函数中花费的时间.例如,如果间隔为100毫秒并且回调需要4000毫秒才能执行,则回调将在100毫秒,4100毫秒等时调用.

我看不到任何可用的内容,所以写了下面的代码.有一个更好的方法吗?

/**
 * Will ensure that only one thread is ever in the callback
 */
public class SingleThreadedTimer : Timer
{
    protected static readonly object InstanceLock = new object();

    //used to check whether timer has been disposed while in call back
    protected bool running = false;

    virtual new public void Start()
    {
        lock (InstanceLock)
        {
            this.AutoReset = false;
            this.Elapsed -= new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
            this.Elapsed += new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
            this.running = true;
            base.Start();
        }

    }

    virtual public void SingleThreadedTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        lock (InstanceLock)
        {
            DoSomethingCool();

            //check if stopped while we were waiting for the lock, we don't want to restart if this is the case..
            if (running)
            {
                this.Start();
            }
        }
    }

    virtual new public void Stop()
    {
        lock (InstanceLock)
        {
            running = false;
            base.Stop();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

fir*_*986 7

这是一个我刚刚敲门的快速例子;

using System.Threading;
//...
public class TimerExample
{
    private System.Threading.Timer m_objTimer;
    private bool m_blnStarted;
    private readonly int m_intTickMs = 1000;
    private object m_objLockObject = new object();

    public TimerExample()
    {
        //Create your timer object, but don't start anything yet
        m_objTimer = new System.Threading.Timer(callback, m_objTimer, Timeout.Infinite, Timeout.Infinite);
    }

    public void Start()
    {
        if (!m_blnStarted)
        {
            lock (m_objLockObject)
            {
                if (!m_blnStarted) //double check after lock to be thread safe
                {
                    m_blnStarted = true;

                    //Make it start in 'm_intTickMs' milliseconds, 
                    //but don't auto callback when it's done (Timeout.Infinite)
                    m_objTimer.Change(m_intTickMs, Timeout.Infinite);
                }
            }
        }
    }

    public void Stop()
    {
        lock (m_objLockObject)
        {
            m_blnStarted = false;
        }
    }

    private void callback(object state)
    {
        System.Diagnostics.Debug.WriteLine("callback invoked");

        //TODO: your code here
        Thread.Sleep(4000);

        //When your code has finished running, wait 'm_intTickMs' milliseconds
        //and call the callback method again, 
        //but don't auto callback (Timeout.Infinite)
        m_objTimer.Change(m_intTickMs, Timeout.Infinite);
    }
}
Run Code Online (Sandbox Code Playgroud)


Lou*_* Go 5

对于任何需要单线程计时器并希望计时器在任务完成开始计时的人。System.Timers.Timer 无需锁定或 [ThreadStatic] 即可实现此目的

System.Timers.Timer tmr;

void InitTimer(){
    tmr = new System.Timers.Timer();
    tmr.Interval = 300;
    tmr.AutoReset = false;
    tmr.Elapsed += OnElapsed;
}

void OnElapsed( object sender, System.Timers.ElapsedEventArgs e )
{
    backgroundWorking();

    // let timer start ticking
    tmr.Enabled = true;
}
Run Code Online (Sandbox Code Playgroud)

归功于Alan N 来源https://www.codeproject.com/Answers/405715/System-Timers-Timer-single-threaded-usage#answer2

编辑:间距