2014-10-10 1 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()은 메인 큐에서 실행됩니다.

제 질문은 올바른 타이밍 모델입니까? 타이머가 1 초마다 작동하지 않으며 너무 의도적으로 멈추지 않습니다. 나는 retVal == 1 일 때 SomeOtherOperation()이 호출되지만 타이머는 아직 완료되지 않았 음을 관찰 할 수 있습니다.

또 다른 참고 : 위의

m_myTimer은 바르, 그리고 그 모든 차이를 만들 수 있다면 내 프로젝트는 ARC입니다.

+0

반복되는 'NSTimer'를 사용하지 않는 이유가 있습니까? –

+0

나는 정밀도를 더 원합니다. NSTimers는 GCD 소스에 비해 정확하지 않습니다. –

답변

0

내 관심은 사물의 정확한보고에 발사 및 중지, 그리고, 시작 정확성에 대해이었다 함께 얼마나 많은 발사 확인할 수 있습니다.

마침내 내 작업 중 하나를 주 대기열 대신 개인 대기열에서 할당하는 결과가 발생했습니다. 이점은 타이머 정확도 및 프롬프트 타이머 취소에서 명확하게 볼 수 있습니다.

는 결론 :

같은 (. ESP 주) 큐는 타이머 작업에 의해 채찍질 점점 더 많은, 더 그들은 부정확된다.

2

아니요. 처리기가 실행 중일 때 발송 타이머가 "건너 뛴다"고 표시되지 않으면 이전 호출이 반환 된 즉시 처리기가 보류중인 이벤트에 대해 다시 호출됩니다.

핸들러가 실행 중이거나 대기열에 들어갈 때 (또는 소스가 일시 중단 된 상태에서) 여러 번의 실행이 발생하면 모든 에지 트리거 된 소스 유형의 경우와 같이 모든 핸들러 호출이 단일 핸들러 호출로 병합됩니다.

당신은 주어진 핸들러 호출이 dispatch_source_get_data()

+0

감사합니다. 나는 이것을 알고 있으며 이미 사용하고 있습니다. 질문은 - 이것을 막을 수있는 방법이 있습니까? 타이머를 취소하는 것은 어떨까요? –

+0

합체를 방지 하시겠습니까? 죄송합니다 (하지만 당신은 분명히 그것을 감지하고 추가 발화는 무시할 수 있습니다). 'dispatch_source_cancel'을 호출하면 해당 함수가 반환 되 자마자 나중에 핸들러가 호출되는 것을 막을 수 있습니다. 마찬가지로 'dispatch_source_set_timer'로 타이머 매개 변수를 변경합니다 (예 : 다음 화재 시간을 영원히 설정) – das