我有几个不同间隔的计时器。任务可以长时间运行并且可能重叠,但在任何时候我都必须确保只有一个任务处于活动状态。我有以下代码与bool变量,我在事件处理程序中设置:
public partial class SomeService : ServiceBase
{
private volatile bool IsActive;
private System.Timers.Timer Timer1;
private System.Timers.Timer Timer2;
protected override void OnStart(string[] args)
{
Timer1 = new System.Timers.Timer();
Timer1.Interval = ConfigurationManager.ImportEveryMinute1 * 60 * 1000;
Timer1.Elapsed += new System.Timers.ElapsedEventHandler(Timer1_Elapsed);
Timer1.Start();
Timer2 = new System.Timers.Timer();
Timer2.Interval = ConfigurationManager.ImportEveryMinute2 * 60 * 1000;
Timer2.Elapsed += new System.Timers.ElapsedEventHandler(Timer2_Elapsed);
Timer2.Start();
}
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!IsActive)
{
IsActive = true;
DoSomeStuff1();
IsActive = false;
}
}
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!IsActive)
{
IsActive = true;
DoSomeStuff2();
IsActive = false;
}
}
}
请告诉我,volatile
关键字在我的情况下是否足够,或者我应该使用锁定,还是有更好的方法可以做到这一点?
答案 0 :(得分:2)
你可以使用SemaphoreSlim。
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
semaphore.Wait();
DoSomeStuff1();
semaphore.Release();
}
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
semaphore.Wait();
DoSomeStuff2();
semaphore.Release();
}
答案 1 :(得分:1)
使用您的解决方案可能会发生
IsActive
变为真。IsActive
上的读写操作是两个操作我建议使用lock
解决方案。
private static object LockObj = new object();
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
lock(LockObj) { /* ... */ }
}
答案 2 :(得分:1)
完全没有,相反,使用disabled=""
只是确保当拥有多个线程时,每个线程都会始终看到最新的值。它对于线程之间的同步没有帮助。
volatile关键字表示某个字段可能被同时执行的多个线程修改。声明为volatile的字段不受编译器优化的约束,这些优化假定由单个线程进行访问。这样可确保始终在字段中显示最新值。
volatile修饰符通常用于多个线程访问的字段,而不使用lock语句来序列化访问。
想象一下两个线程都到达
volatile
他们都看到了最新值(if (!IsActive)
)
一个进步,然后另一个。现在他们都在里面。
如果要进行线程同步,则必须使用某种锁定机制,如false
。
请注意,对于您的实现(事件是否有效),线程不会相互等待,如果另一个线程处于活动状态,它们就会退出。
您可能需要查看dataflow,它可能更适合您的需求。
答案 3 :(得分:-1)
用这样的东西替换你的计时器:
private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock(IsActive)
{
DoSomeStuff1();
}
}
private void Timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock(IsActive)
{
DoSomeStuff2();
}
}