2011-06-23 169 views
1

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

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

我写了一些代码,其中客户端使用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); 

       } 
     } 


    } 

但我的定时器一个奇怪的行为方式,从不调用管理方法.. 能否请你检查一下为什么?或任何其他逻辑需要在这里实施。

感谢 普里

回答

0

在静态主类实例化一个计时器,并创建一个经过的事件处理程序定时器去当5秒之后。

在已经过的事件处理程序中,调用您想要每5秒运行一次的方法。请记住,计时器和事件处理的线程跨度,所以你需要认识到,你可以有两个事件发生在同一时间 - 在THEAD安全满耳意味着代码...定时器

http://msdn.microsoft.com/en-us/library/system.timers.timer(v=VS.71).aspx

我只是重新读你的文章,你正在使用一个计时器...请记住THREADSAFE。如果您在进入需要调用的方法之前需要停止计时器,那么甚至会发生流逝。

1

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