如何每5秒调用一次方法?

时间:2011-06-23 08:35:56

标签: c# asp.net

我有两个wcf服务Client.svc和Admin.svc。 客户端中的方法每5秒调用一次admin服务方法。客户端调用的Admin方法验证如果在5秒内未调用此方法,则更新状态为“NotResponding”的数据库,否则使用“IsAlive”值更新它。

所有这些都应该在一个单独的线程上完成。

我编写了一些代码,其中Client使用Timer每隔5秒调用一次该方法。

    public static void RegisterHeartBeat(PingRequest pingRequest)
    {
        try
        {

            string heartBeatInterval = Phoenix.API.Utility.ConfigReader.GetAppSettingsValue("HeartBeatInterval");
            int timeInSeconds = -1;

            Int32.TryParse(heartBeatInterval, out timeInSeconds);

            if (timeInSeconds != -1)
            {
                TimerCallback timerCallHeartBeat = new TimerCallback(CallRegisterHeartBeat);
                Timer timer = new Timer(timerCallHeartBeat, pingRequest, 0, (timeInSeconds * 1000)); //Multiplying by 1000, converts seconds to milliseconds
            }
            else
            {
                Exception ex = new Exception("HeartBeatInterval is not configured in web.config file");
                Phoenix.Client.API.BLL.Common.CommonUtility.CreateResultAndLogClientException(null, null, ex);
            }
        }
        catch (Exception ex)
        {
            Phoenix.Client.API.BLL.Common.CommonUtility.CreateResultAndLogClientException(null, null, ex);
        }

    }


    private static void CallRegisterHeartBeat(object state)
    {
        PhoenixClientBLL.Admin.InternalClient internalClient = new PhoenixClientBLL.Admin.InternalClient("BasicHttpBinding_IInternal");

        if (state != null)
        {
            //AdminAPI accepts Admin.PingRequest parameter which has a different format than ClientAPI PingRequest. 
            //Thus, a new object of admin ping request type is created.
            Phoenix.API.ClientServiceContracts.DataContracts.PingRequest pingRequestDC = state as Phoenix.API.ClientServiceContracts.DataContracts.PingRequest;

           //AdminAPI
            PhoenixClientBLL.Admin.PingRequest pingRequest = new PhoenixClientBLL.Admin.PingRequest();

            //Test Agent ID
            pingRequest.TestAgentId = Guid.Parse(pingRequestDC.TestAgentId);

            //Test Agent Status is not set because it will be decided in ADMIN API as per the interval difference.
            internalClient.RegisterHeartBeat(pingRequest);

        }

    }

在管理员中,我检查上次更新日期和当前日期以及相应更新数据库的时间差。

    public static void RegisterHeartBeat(PingRequest pingRequest)
    {
        int status = 0;
        DateTime startTime, endTime;
        int testAgentId = -1;
        string heartBeatIntervalValue = Phoenix.API.Utility.ConfigReader.GetAppSettingsValue("HeartBeatInterval");
        int heartBeatInterval = -1;

        if(String.IsNullOrEmpty(heartBeatIntervalValue))
        {
             Common.CommonUtility.CreateResultAndLogException(null, null, new Exception("HeartBeatInterval is not configured in the configuration file"));
        }
        else
        {
                try
                {
                    string key = pingRequest.TestAgentId.ToString();
                    if (!String.IsNullOrEmpty(key))
                    {
                        if (!heartBeatTimeStamp.ContainsKey(key))
                        {
                            heartBeatTimeStamp.Add(key, System.DateTime.Now);
                        }
                        else
                        {

                            endTime = DateTime.Now;
                            if (heartBeatTimeStamp[key].HasValue)
                            {
                                startTime = heartBeatTimeStamp[key].Value;
                                var timeDiff = new TimeSpan(endTime.Ticks - startTime.Ticks);

                                //Check the configured heart beat interval value
                                Int32.TryParse(heartBeatIntervalValue, out heartBeatInterval);

                                if (heartBeatInterval != -1)
                                {
                                    if (timeDiff.Seconds > heartBeatInterval)
                                    {
                                        // add update NotResponding = 3 ..
                                        Int32.TryParse(pingRequest.TestAgentId.ToString(), out testAgentId);

                                        //If Test Agent ID is converted into integer than update table else log the error.
                                        if (testAgentId != -1)
                                        {
                                            status = DAO.TestAgentDAO.RegisterHeartBeat(testAgentId, (int)TestAgentStatus.NotResponding);
                                        }
                                        else
                                        {
                                            Common.CommonUtility.CreateResultAndLogException(null, null, new Exception("Cannot convert Test Agent ID Data type from GUID to Integer"));
                                        }

                                        //Sql Error
                                        if (0 != status)
                                        {
                                            Common.CommonUtility.CreateResultAndLogSqlError(null, status, null);

                                        }
                                    }
                                    else
                                    {
                                        // add update IsAlive= 4
                                        Int32.TryParse(pingRequest.TestAgentId.ToString(), out testAgentId);

                                        //If Test Agent ID is converted into integer than update table else log the error.
                                        if (testAgentId != -1)
                                        {
                                            status = DAO.TestAgentDAO.RegisterHeartBeat(testAgentId, (int)TestAgentStatus.IsAlive);
                                        }
                                        else
                                        {
                                            Common.CommonUtility.CreateResultAndLogException(null, null, new Exception("Cannot convert Test Agent ID Data type from GUID to Integer"));
                                        }

                                        //Sql Error
                                        if (0 != status)
                                        {
                                            Common.CommonUtility.CreateResultAndLogSqlError(null, status, null);

                                        }
                                    }
                                }
                                else
                                {
                                    Common.CommonUtility.CreateResultAndLogException(null, null, new Exception("Invalid HeartBeatInterval Value"));
                                }


                            }
                        }
                    }
                    else
                    {
                        Common.CommonUtility.CreateResultAndLogException(null, null, new Exception("Test Agent ID is incorrect or does not exists"));
                    }
                }
                catch (Exception ex)
                {
                    Common.CommonUtility.CreateResultAndLogException(null, null, ex);

                }
        }


    }

但我的计时器表现得很糟糕,从不调用管理员方法。 你能检查一下为什么吗?或者需要在这里实施任何其他逻辑。

由于 普里

3 个答案:

答案 0 :(得分:1)

您可以使用调度程序而不是计时器。有一个可用于.NET的开源调度程序Quartz .Net。这可以每5秒触发一次你的电话。

答案 1 :(得分:0)

你是否在任何地方启动计时器?或者将Enabled设置为true?

http://msdn.microsoft.com/en-us/library/system.timers.timer.start.aspx

答案 2 :(得分:0)

在静态主类中实例化一个计时器,并为计时器创建一个已用事件处理程序,以便在5秒钟时启动。

在已用事件处理程序中

,调用要每5秒运行一次的方法。请记住计时器和事件处理程序跨度线程,因此您需要意识到您可能同时发生两个事件 - 这意味着代码安全可靠......

计时器的示例 http://msdn.microsoft.com/en-us/library/system.timers.timer(v=VS.71).aspx

我只是重读你的帖子,你正在使用计时器......请记住THREADSAFE。如果你需要在进入方法之前停止你的计时器,你需要在经过的时候调用它。