2014-11-04 91 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