Jos*_*ers 18 c# multithreading timer overlap
我正在编写一个Windows服务,每隔一段时间运行一次可变长度的活动(数据库扫描和更新).我需要经常运行此任务,但要处理的代码并不安全地同时运行多次.
我怎样才能最简单地设置一个计时器来每隔30秒运行一次任务,而不会重复执行?(我假设System.Threading.Timer这个工作是正确的计时器,但可能会弄错).
Ree*_*sey 31
您可以使用Timer执行此操作,但您需要在数据库扫描和更新时使用某种形式的锁定.简单lock的同步可能足以防止发生多次运行.
话虽如此,在操作完成后启动计时器可能会更好,只需使用一次,然后停止它.在下一次操作后重新启动它.这将在事件之间给你30秒(或N秒),没有重叠的可能性,也没有锁定.
示例:
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((g) =>
{
Console.WriteLine(1); //do whatever
timer.Change(5000, Timeout.Infinite);
}, null, 0, Timeout.Infinite);
Run Code Online (Sandbox Code Playgroud)
立即工作.....完成......等待5秒....立即工作.....完成......等待5秒....
jsw*_*jsw 23
我在你已用完的代码中使用了Monitor.TryEnter:
if (Monitor.TryEnter(lockobj))
{
try
{
// we got the lock, do your work
}
finally
{
Monitor.Exit(lockobj);
}
}
else
{
// another elapsed has the lock
}
Run Code Online (Sandbox Code Playgroud)
Jim*_*hel 15
我喜欢这样System.Threading.Timer的事情,因为我不需要经历事件处理机制:
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, 30000);
object updateLock = new object();
void UpdateCallback(object state)
{
if (Monitor.TryEnter(updateLock))
{
try
{
// do stuff here
}
finally
{
Monitor.Exit(updateLock);
}
}
else
{
// previous timer tick took too long.
// so do nothing this time through.
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过使计时器一次性完成并在每次更新后重新启动它来消除锁定的需要:
// Initialize timer as a one-shot
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, Timeout.Infinite);
void UpdateCallback(object state)
{
// do stuff here
// re-enable the timer
UpdateTimer.Change(30000, Timeout.Infinite);
}
Run Code Online (Sandbox Code Playgroud)