简体   繁体   English

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

[英]How to call a method in every 5 seconds?

I have two wcf services Client.svc and Admin.svc. 我有两个wcf服务Client.svc和Admin.svc。 A method in client calls admin service method in every 5 seconds. 客户端中的方法每5秒钟调用一次admin服务方法。 And Admin's method which is been called by client verifies that if this method is not called within 5 seconds then update database with status "NotResponding" else update it with "IsAlive" value. 客户端调用的Admin方法将验证如果在5秒内未调用此方法,则更新状态为“ NotResponding”的数据库,否则将其更新为“ IsAlive”值。

All this should be done on a separate thread. 所有这些都应该在单独的线程上完成。

I have written some code wherein Client uses Timer to call that method in every 5 seconds. 我编写了一些代码,其中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);

        }

    }

In Admin, I check the last update date and the current date with the difference of time to update database accordingly. 在“管理员”中,我检查上次更新日期和当前日期以及更新数据库的时间差。

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

                }
        }


    }

But my timer behaves in a wierd manner and never calls the admin method.. Can you please check it why? 但是我的计时器行为异常,从不调用admin方法。.请问为什么? or any other logic needs to be implemented here. 或任何其他逻辑都需要在这里实现。

Thanks Priyanka 谢谢普里扬卡

You can probably use a scheduler instead of a timer. 您可能可以使用调度程序而不是计时器。 There is an open source scheduler Quartz .Net available for .NET. 有一个可用于.NET的开源调度程序Quartz .Net This can trigger your calls every 5 seconds. 这可以每5秒触发一次呼叫。

Are you starting the Timer anywhere? 您在任何地方启动计时器吗? Or setting Enabled to true? 还是将“启用”设置为true?

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

In your static main class instantiate a timer and create a elapsed event handler for the timer to go to when the 5 seconds are up. 在您的静态主类中实例化一个计时器,并为该计时器创建一个经过的事件处理程序,以在5秒钟结束时转到该计时器。

in the elapsed event handler, call your method you want to run every 5 seconds. 在过去的事件处理程序中,每5秒调用一次您要运行的方法。 Keep in mind the timer and event handler span threads so you need to realize you could have two events happening at the same time - meaning code in a thead safe maner... 请记住,计时器和事件处理程序跨越线程,因此您需要意识到可能同时发生两个事件-这意味着在thead安全管理器中的代码...

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

i just reread your post, you are using a timer... Keep in mind THREADSAFE. 我只是重新阅读了您的帖子,您正在使用计时器...请记住THREADSAFE。 if you need to stop your timer before going into the method you need called when the elapsed even ocurs. 如果您需要先停止计时器再进入需要经过的方法,甚至在经过时调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM