Windows服务中的Timer Elapsed事件一一

Posted

技术标签:

【中文标题】Windows服务中的Timer Elapsed事件一一【英文标题】:Timer Elapsed event one by one in Windows Service 【发布时间】:2016-04-24 21:49:18 【问题描述】:

我在 C# 中创建 Windows 服务。我使用 timer elapsed 方法对数据库执行一些 CRUD 操作。例如

tmrAPACSEvent = new Timer(10000);
tmrAPACSEvent.Elapsed += new ElapsedEventHandler(tmrAPACSEvent_Elapsed);
tmrAPACSEvent.Enabled = true;

我在 OnStart 方法中创建了这个计时器,而 Event 是

private void tmrAPACSEvent_Elapsed(object sender, ElapsedEventArgs e)

    Library.WriteErrorLog("tmrAPACSEvent ticked and some job has been done successfully");

    try
    
        var UnProcessedEvents = BLCustomService.GetCustomEvents();

        if (UnProcessedEvents != null)
        
            foreach (EventData eventData in UnProcessedEvents)
            
                Library.WriteErrorLog(BLCustomService.ChangeEventStatus(eventData).ToString());
                Library.WriteErrorLog(eventData.EventId.ToString());
                var ed = new EventData()
                
                    dtRealDateTime = eventData.dtRealDateTime,
                    dwCardNumber = eventData.dwCardNumber,
                    strHolderName = eventData.strHolderName,
                    strInitObjName = eventData.strInitObjName
                ;

                ed = BLCustomService.AddEvent(ed);
            
            Library.WriteErrorLog("Events added");
        
    
    catch (Exception exception)
    
        Library.WriteErrorLog("Error 96: " + exception.StackTrace);
    

当我启动服务时,事件会并行执行,我会在数据库中获得多个对应“事件”的数据。我知道操作时间大于计时器经过时间。但我希望每个线程都必须等待在其之前启动的其他线程完成。

--可能的解决方案-- 我创建了全局静态布尔变量,然后将其赋值为 true。在我的事件中将其添加到 if 条件中,然后我将其分配为 false 直到 foreach 循环结束。

  private static bool adminForElapsedEvent = true;
    private void tmrAPACSEvent_Elapsed(object sender, ElapsedEventArgs e)
    
        Library.WriteErrorLog("tmrAPACSEvent ticked and some job has been done successfully");

        try
        
            var UnProcessedEvents = BLCustomService.GetCustomEvents();

            //Library.WriteErrorLog("tmrAPACSEvent ticked and some job has been done successfully" + UnProcessedEvents.Count);
            if (UnProcessedEvents != null || adminForElapsedEvent)
            
                adminForElapsedEvent = false;

                // doing some wordks
                adminForElapsedEvent = true;
            
        
        catch (Exception exception)
        
            Library.WriteErrorLog("Error 96: " + exception.StackTrace);
        
    

此方法第一次有效,但几分钟后 Elapse 事件再次运行,并重复插入。

【问题讨论】:

【参考方案1】:

您可以尝试的第一件事:设置您的 tmrAPACSEvent.Enabled = false 而不是 adminForElapsedEvent = false;。那么你甚至不需要全局变量。

这不是万无一失的,因为您遇到了竞争条件。因此,下一个建议是锁定您的代码。但是不要使用普通锁,使用Mutex 我发现它可以提供更好的资源访问控制。所以你的代码现在看起来像这样:

// Create a new Mutex. The creating thread does not own the mutex.
private static Mutex mux = new Mutex();

private void tmrAPACSEvent_Elapsed(object sender, ElapsedEventArgs e)

    Library.WriteErrorLog("tmrAPACSEvent ticked and some job has been done successfully");

    try
    
        var UnProcessedEvents = BLCustomService.GetCustomEvents();

        if (UnProcessedEvents != null)
        
            tmrAPACSEvent.Enabled = false;

            // Wait until it is safe to enter, and do not enter if the request times out.
            if (mux.WaitOne(7000))
            
                // do work

                // note this is inside the mutex so that the timer is guaranteed enabled, even for just a moment
                tmrAPACSEvent.Enabled = true;
            
        
    
    catch (Exception exception)
    
        Library.WriteErrorLog("Error 96: " + exception.StackTrace);
    

【讨论】:

非常感谢您的回答,@Balah。我只能在两天后尝试。这是我的工作,明天我们不工作)) 祝你好运 ;) 祝你好运!

以上是关于Windows服务中的Timer Elapsed事件一一的主要内容,如果未能解决你的问题,请参考以下文章

Windows服务时间控件怎么调试

用C#写一个windows服务可定时执行sql Service数据库里面的存储过程(带两个参数),急求代码!高手赐教!

C# Timer.Elapsed 事件连续触发两次

Timer应用之Interval优化

使用 StructureMap 在 Timer_Elapsed 中处理 Datacontext 操作

为啥 System.Timers.Timer 在触发 Elapsed 事件时会创建多个线程?