我有两个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);
}
}
}
但我的计时器表现得很糟糕,从不调用管理员方法。 你能检查一下为什么吗?或者需要在这里实施任何其他逻辑。
由于 普里
答案 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。如果你需要在进入方法之前停止你的计时器,你需要在经过的时候调用它。