2014-11-03 1 views
0

이상한 Grand Central Dispatch 타이머 동작에 직면했습니다. 그것은 발사의 시간을 깨고 몇 초 동결됩니다. "온라인"상태로 유지하려면 서버를 핑 (ping)해야하지만이 동작은 적합하지 않습니다.이상한 GCD 타이머 동작

여기 타이머 생성 코드입니다.

// pingTimer and pingQueue are class members 
- (void)createPingTimerSource 
    { 
    // check timer exists 
    if(pingTimer) 
    { 
     // suspend source and cancel 
     [self setPingTimerSuspended:YES]; 
     dispatch_source_cancel(pingTimer); 
    } 
    // check having queue, create if doesn't exist 
    if(!pingQueue) 
     pingQueue = dispatch_queue_create(kDispatchTimerQueueLabel, NULL); 
    // create timer dispatch source 
    pingTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, pingQueue); 
    dispatch_source_set_timer(pingTimer, dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_MSEC), 5*NSEC_PER_MSEC, NSEC_PER_SEC/10); 
    // set event handler 
    dispatch_source_set_event_handler(pingTimer,^{ 
     printf("[%llu] gcd timer fired.\n", mach_absolute_time()/NSEC_PER_SEC); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     [self sendPingToServer]; 
     }); 
    }); 
    // set cancel handler 
    dispatch_source_set_cancel_handler(pingTimer, ^{ 
     // release dispatch source if exists 
     if(pingTimer) 
     dispatch_release(pingTimer); 
     // check timer queue exists and release if does 
     if(pingQueue) 
     dispatch_release(pingQueue); 
    }); 
    } 

여기서 로그 콘솔이 촬영되었습니다.

Debug console content

도움을 주셔서 감사합니다.

답변

1

가능성의 몇 가지 :

  1. 귀하의 pingQueue 일을하고 차단 될 수 있습니다 및 직렬 큐, 이전의 파견 블록 완료 및 대기열까지 새로운 파견 블록을 수행 할 수 없습니다 다시 사용할 수 있습니다.

    핑 루틴의 시작과 중지를 로깅하고 실제로 타이머가 작동하지 않는 문제인지 확인하고 큐가 차단되어 새로운 타이머 요청을 수행 할 수 없는지 확인하십시오.

  2. 앱이 포 그라운드가 아닌 경우 "App Nap"기능이 타이머를 병합하여 전력 소모를 최소화하려고 할 수 있습니다. 따라서 타이머는 예상 한 빈도로 호출 할 수 없습니다.

    절대적으로 필요하지 않는 한이 분명히 (예 : 타이머 편차를 허용 할 수없는 하드웨어와 인터페이스) 권장하지 않습니다하지만 당신이 전력 절감 앱 낮잠을 잃게과 같이, dispatch_source_create 세 번째 매개 변수로 DISPATCH_TIMER_STRICT을 제공하여 참여하지 귀하의 타이머를 알 수

    제공합니다.

    WWDC 2013 video Improving Power Efficiency with App Nap을 참조하십시오.

+0

네가 맞다. 도와 줘서 고마워! – Astoria

1

dispatch_queue_create이 블록 처리를위한 독립적 인 스레드를 생성한다는 보장은 없습니다. 여기

가 실행 동시에 실행할 수있는 독립적 인 전송 대기열 블록의 특정 스레드에 결합되지 Apple documentation
큐에서 인용된다.

이렇게하면 많은 대기열에 압력이 가해지면 pingQueue가 응답을 중지하고 지연된 블록을 실행할 수 있습니다.