任何时候只有一个活动任务

时间:2017-04-03 12:18:52

标签: c# multithreading timer

我有几个不同间隔的计时器。任务可以长时间运行并且可能重叠,但在任何时候我都必须确保只有一个任务处于活动状态。我有以下代码与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关键字在我的情况下是否足够,或者我应该使用锁定,还是有更好的方法可以做到这一点?

4 个答案:

答案 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();
    }
}