【问题标题】:Timed events overlapping during execution执行期间重叠的定时事件
【发布时间】:2016-07-29 10:32:18
【问题描述】:

我在使用用于执行自动化任务的服务时遇到问题。 该服务使用计时器并在 20 秒后执行。

执行的函数打开数据库,从中读取,通过网络发送值,接收响应并使用该响应更新数据库。

它一直运行良好,直到我想对数据库中的大约 1000 行执行自动化任务并且系统“失败”。检查我的日志后,我发现该函数在间隔之后执行,即使前一个实例仍在执行。该功能应该发送一条消息,一些客户抱怨没有收到一条消息,而另一些则收到了多达六次。

如果之前的实例仍在运行,是否有任何简单有效的方法来确保函数不会运行。

如果我在函数中启动和停止时间,它只会将“经过”的时间添加到间隔中

这里是代码

public partial class Service1 : ServiceBase
{
    private Timer timer1 = null;

    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        timer1 = new Timer();
        this.timer1.Interval = 20000;
        this.timer1.Elapsed += new  System.Timers.ElapsedEventHandler(this.timer1_Tick);
        timer1.Enabled = true;
        Library.WriteErrorLog("service has started");
    }

    private void timer1_Tick(object sender, ElapsedEventArgs e)
    {
        try
        {
        //retrieve data from database
        //read rows

        //Loop through rows
        //send values through network
        //receive response and update db
        }
        catch (Exception ex)
        {
            Library.WriteErrorLog(ex);
        }
    }
}

    protected override void OnStop()
    {
        timer1.Enabled = false;
        Library.WriteErrorLog("service has stopped");
    }
}

【问题讨论】:

  • 在做其他事情之前停止你的滴答声中的计时器,然后在finally 中再次启动它就足够了吗?或者无论如何你都想保持计时器运行?这将确保在任何给定时间只有一个计时器运行。
  • 感谢@Kevin Lee 的回复。

标签: c# multithreading service timer


【解决方案1】:

您正在使用多线程 System.Timers.Timer,它在每个 Elapsed 事件的 ThreadPool 中调用新线程上的 timer1_Tick 回调。使用变量来同步执行。

   public partial class Service1 : ServiceBase
    {

        private Timer timer1 = null;
        private long isTaskRunning = 0;

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            timer1 = new Timer();
            this.timer1.Interval = 20000;
            this.timer1.Elapsed += new  System.Timers.ElapsedEventHandler(this.timer1_Tick);
            timer1.Enabled = true;
            Library.WriteErrorLog("service has started");
        }

        private void timer1_Tick(object sender, ElapsedEventArgs e)
        {
            try
            {

            if (Interlocked.CompareExchange(ref isTaskRunning, 1, 0)==1)
            {
             return;
            }

            //retrieve data from database
            //read rows

            //Loop through rows
            //send values through network
            //receive response and update db
            }
            catch (Exception ex)
            {
                Library.WriteErrorLog(ex);
            }
            finally
            {
             Interlocked.Exchange(ref isTaskRunning, 0);
            }
        }
    }

        protected override void OnStop()
        {
            timer1.Enabled = false;
            Library.WriteErrorLog("service has stopped");
        }
    }

【讨论】:

  • 我使用System.Timers 作为代码,但InterLockSystem.Threading.Timer 中的方法。这不会引起冲突吗?很抱歉我的许多问题,我对线程有点陌生。谢谢
  • 不会有任何冲突。回调不会被多个线程同时执行。互锁方法可以防止这种情况
  • 感谢您的回复。
【解决方案2】:
private void timer1_Tick(object sender, ElapsedEventArgs e)
{
    Timer timer = sender as Timer;
    timer.Enabled = false;  // stop timer
    try
    {
         //retrieve data from database
         //read rows

         //Loop through rows
         //send values through network
         //receive response and update db
     }
     catch (Exception ex)
     {
         Library.WriteErrorLog(ex);
     }
     finally
     {
         timer.Enabled = true;   // start timer again, no overlapping
     }
 }

【讨论】:

    猜你喜欢
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    相关资源
    最近更新 更多