2014-11-04 93 views
2

我已经给了一个任务来编写一个程序来计算从我们的网站请求多少页面浏览量。我目前的做法是从谷歌分析实时API获取数据,这对我的惊喜起作用。C#调用方法每分钟55秒

我的问题是,为了获得浏览量的每一分钟,我需要查询从谷歌API数据的两倍(因为它返回从重置每分钟的计时器达29分钟加一值之和)。在设置“重置点”之后,我们只需说每分钟55秒就会在第56分钟和随后的第53分钟轮询数据,这使我对新用户/请求的页面访问有了较好的估计。

所以这是我目前的做法:

static System.Timers.Timer myTimer = new System.Timers.Timer(); 
myTimer.AutoReset = false; 
myTimer.Interval = interval(); 
myTimer.Elapsed += myTimer_Elapsed2; 
myTimer.Start(); 

static double interval() 
    { 
     return 1000 - DateTime.Now.Millisecond; 
    } 

static void myTimer_Elapsed2(object sender, System.Timers.ElapsedEventArgs e) 
    { 
    if (DateTime.Now.Second == (resetPoint.Second - 1) % 60 && warden) 
      { 
     DoStuff(); //mostly inserting google API data to database 
      } 
else if (DateTime.Now.Second == (resetPoint.Second + 1) % 60) //so we dont get riddiculous 60 and above 
    { 
    //I get some data here, to later use it in DoStuff - mostly to calculate the gap between later 
    } 
     myTimer.Interval = interval(); //Because DoStuff() takes about 0.5 sec to execute, i need to recalibrate 
     myTimer.Start(); 
    } 

和它的作品真的很好,直到它停止约2小时后,现在我不知道为什么(程序运行,只是计时器没有做它工作了)。

如何长时间保持稳定?最好的情况是在没有干预的情况下运行数月。

@我编辑给一个更好的感觉是什么,我实际上做

@END学分

我结束了使用两个定时器,在一分钟一圈的每个运行。数据库写作有时会崩溃,我没有正确处理相应的异常。 Log告诉我,google API函数会不时地检索数据,导致多个Threading.Event调用,并使我的数据库数据处理抛出异常,从而停止定时器。

我试图用石英的方法,但是它缺乏人性化的HOWTO的让我放弃这个库。

+7

您可能已达到Google API限制限制吗? – Nzall 2014-11-04 14:35:29

+0

不,谷歌允许我每天轮询数据5万次,对于这项任务,我只需要大约4千(一天1440分钟* 2 +校准开始) – Luntri 2014-11-04 14:42:17

+0

我认为你可以将'%60'离开因为'秒'从0运行到59.并且不需要每次启动定时器。而且,当毫秒为999时,你的消息队列会填充很多定时器消息。如果发生在第55秒,您可能会压倒GoogleAPI。 – Sjips 2014-11-04 14:42:58

回答

1

.NET定时器是可靠的。也就是说,它不会随意停止工作,因为没有明显的原因。

最有可能的东西在你的计时器事件处理程序抛出异常,这是不是因为浮出水面南瓜System.Timers.Timer例外。 As the documentation states:

Timer组件捕获并抑制事件处理程序为Elapsed事件抛出的所有异常。此行为在未来的.NET Framework版本中可能会发生变化。

关于“可能发生变化”的行为,至少在.NET 2.0中已经存在。

我认为发生的事情是计时器调用你的事件处理程序。事件处理程序或其调用的某个方法会引发异常,并且计时器会将它放在地板上,因为您不处理它。

您需要在您的myTimer_Elapsed2方法中放置异常处理程序,以便至少记录任何突然出现的异常。利用异常日志提供的信息,您可能可以确定问题所在。

更好的是,停止使用System.Timers.Timer。改为使用System.Threading.Timer

最后,没有办法像编写的代码一样,在每分钟,每分钟的精确时间内准确地给出一个计时器。计时器不准确。它每分钟会关闭几毫秒。随着时间的推移,它将开始在54秒(或者56),然后是53(或57)等时开始滴答滴答。如果你真的需要这个在过去一分钟55秒内可靠地打勾,那么你需要重置计时器在每分钟后,考虑当前时间。

我怀疑你需要检查精确到55秒的每一分钟是否过分。只需将您的计时器设置为每分钟计时一次,然后确定自上次计时以来的确切运行时间。所以一个“分钟”可能是61或62秒,另一个可能是58或59秒。如果您存储了请求数量和经过时间,后续处理可以平滑颠簸并为您提供可靠的每分钟请求数。试图收集关于的确切数据一分钟的界限将非常困难,甚至可能会出现像Windows这样的非实时操作系统。

3

你真的应该考虑使用Quartz.net一个可靠的基础上,安排事件。使用计时器进行计划是要求比赛条件,事件跳过和数据库死锁等内容。

http://www.quartz-scheduler.net/允许你安排在精确的时间间隔的事件,当你的代码开始或停止独立的。

你如何使用它的一个例子:这将建立一个触发器,它会自动攻击下一个小时的顶部,然后重复每2个小时,永远:

trigger = TriggerBuilder.Create() 
    .WithIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group 
    .StartAt(DateBuilder.EvenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00")) 
    .WithSimpleSchedule(x => x 
     .WithIntervalInHours(2) 
     .RepeatForever()) 
    // note that in this example, 'forJob(..)' is not called 
    // - which is valid if the trigger is passed to the scheduler along with the job 
    .Build(); 

scheduler.scheduleJob(trigger, job); 

http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/simpletriggers.html有几个例子。我真的很乐意使用它,因为它会严重地简化开发。

+0

这对我来说有点矫枉过正,学习新图书馆做一个相当简单的任务:( – Luntri 2014-11-05 14:13:10