计时器在Windows服务中逐个完成事件

时间:2016-01-19 12:11:37

标签: c# multithreading events timer windows-services

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

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

我在OnStart方法中创建此计时器,而事件是

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);
    }
}

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

- 可能的解决方案 - 我创建全局静态bool变量nad赋值为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 个答案:

答案 0 :(得分: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);
    }
}