pro*_*ach 6 c# multithreading timer
我想要一个具有以下属性的计时器:
无论启动多少次调用,只有一个回调线程正在运行
关于间隔,忽略了在回调函数中花费的时间.例如,如果间隔为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)
这是一个我刚刚敲门的快速例子;
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)
对于任何需要单线程计时器并希望计时器在任务完成后开始计时的人。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
编辑:间距