2014-10-10 66 views
0

我閱讀了文檔,發現如果處理程序仍在進行之前的迭代,則定時器(dispatch_source_t)將跳過觸發。dispatch_source_t處理函數的時序問題 - 我是否遵循調度計時器的正確模式?

但是,處理器的整個業務需要更長的時間,這使得這個不準確。而且我正在觀察,我無法在預定的時間停止計時器。

我的代碼如下所示:

double secondsToFire = 1.0f; 
dispatch_queue_t queue = dispatch_get_main_queue(); 
m_myTimer = CreateDispatchTimer(secondsToFire, queue, 
^{  
    //Do some time consuming operation, taking any number of seconds 
    int retVal = DoSomeOperation(); 

    if (retVal == 1) 
    { 
     cancelTimer(m_myTimer); 
     SomeOtherOperation();    
    } 
}); 

dispatch_source_t CreateDispatchTimer(double interval, dispatch_queue_t queue, dispatch_block_t block) 
{ 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 
    if (timer) 
    { 
    // dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, (1ull * NSEC_PER_SEC)/10); 

     dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval * NSEC_PER_SEC, 0); 
     dispatch_source_set_event_handler(timer, block); 
     dispatch_resume(timer); 
    } 
    return timer; 
} 

void cancelTimer(dispatch_source_t _timer) 
{ 
    if (_timer) 
    { 
     dispatch_source_cancel(_timer); 
     _timer = nil; 
    } 
} 

注:

裏面DoSomeOperation(),我有附帶@synchronized(array),在我訪問誰是被另一個私人隊列寫的陣列碼。但是整個DoSomeOperation()在主隊列上執行。

我的問題是,這是正確和準確的時間模型?我在這裏發帖是因爲我面臨着很多不準確的情況 - 計時器不會每秒都會觸發,而且它也不會像預期的那樣停止。我能夠觀察到SomeOtherOperation()retVal == 1時被調用,但是定時器尚未完成。

另注:

m_myTimer以上是伊娃,我的項目是ARC,如果能夠有任何區別。

+0

有沒有原因你不使用重複'NSTimer'? – 2014-10-10 19:18:57

+0

我想要更精確 - 與GCD源相比,NSTimers不是很準確。 – 2014-10-10 19:19:54

回答

0

我關心的是關於首發的準確性,在兩不誤報告射擊和停止,而不是。

我終於把我的一個任務從私有隊列中分配出來,而不是從主隊列中分配出來。在定時器精度和提示定時器取消時,優勢可以清晰可見。

結論:

更多相同(ESP主)隊列中獲取由定時器任務鞭打,他們越不準確。

2

不,調度計時器如果在處理程序正在運行時觸發,則不會「跳過」,一旦前一次調用返回,處理程序將立即重新調用該未決事件。

如果在處理程序正在運行或排隊(或源被掛起時)時發生多次觸發,它們將全部獲取合併到單個處理程序調用中(如所有邊緣觸發源類型的情況)。

您可以檢查一個給定的處理程序調用多少點火是與dispatch_source_get_data()

+0

謝謝,我知道這一點,我已經在使用它。問題是 - 有沒有辦法預防這種情況?另外,取消定時器呢? – 2014-10-11 05:29:52

+0

阻止合併?沒有,抱歉(但你可以明顯地發現它,並忽略額外的發射)。 調用'dispatch_source_cancel'將會在函數返回後立即阻止處理程序的將來調用,同樣會使用'dispatch_source_set_timer'改變定時器參數(例如將下一次着火時間設置爲永久) – das 2014-10-12 23:54:47