[objective-c] 메인 스레드에서 작업을 수행하는 GCD

어떤 스레드에서나 콜백이 있습니다. 이 콜백을 받으면 메인 스레드에서 특정 작업을 수행하고 싶습니다.

이미 메인 스레드에 있는지 확인해야합니까, 아니면 아래 코드를 호출하기 전에이 확인을 수행하지 않으면 페널티가 있습니까?

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here
});



답변

아니요, 이미 메인 스레드에 있는지 여부를 확인할 필요가 없습니다. 블록을 메인 큐에 디스패치하면 블록이 메인 스레드에서 직렬로 실행되도록 예약하는 것입니다. 해당 실행 루프가 실행될 때 발생합니다.

메인 스레드에 이미있는 경우 동작은 동일합니다. 블록이 예약되고 메인 스레드의 실행 루프가 실행될 때 실행됩니다.


답변

위에서 설명한 비동기 디스패치 사례의 경우 메인 스레드에 있는지 확인할 필요가 없습니다. Bavarious에서 알 수 있듯이 이것은 메인 스레드에서 실행되도록 대기합니다.

그러나 a를 사용하여 위의 작업을 시도하고 dispatch_sync()콜백이 기본 스레드에 있으면 해당 시점에서 애플리케이션이 교착 상태가됩니다. 이 동작은 코드를 이동할 때 놀랐 기 때문에 여기 에 내 대답에 이것을 설명합니다 -performSelectorOnMainThread:. 내가 언급했듯이 도우미 함수를 만들었습니다.

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

현재 사용중인 메소드가 현재 메인 스레드에없는 경우 메인 스레드에서 동기식으로 블록을 실행하고 블록이 있으면 인라인으로 실행합니다. 다음과 같은 구문을 사용하여이를 사용할 수 있습니다.

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});


답변

다른 답변에서 언급했듯이 기본 스레드의 dispatch_async가 좋습니다.

그러나 유스 케이스에 따라 단점을 고려할 수있는 부작용이 있습니다. 블록이 큐에서 스케줄되므로 제어가 실행 루프로 돌아갈 때까지 실행되지 않으므로 지연 효과가 있습니다. 블록의 실행.

예를 들어

NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");

인쇄합니다 :

before dispatch async
after dispatch async
inside dispatch async block main thread from main thread

따라서 외부 NSLog 사이에서 블록이 실행될 것으로 예상하면 dispatch_async가 도움이되지 않습니다.


답변

메인 스레드에 있는지 확인할 필요가 없습니다. Swift에서이를 수행하는 방법은 다음과 같습니다.

runThisInMainThread { () -> Void in
    runThisInMainThread { () -> Void in
        // No problem
    }
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

내 저장소에 표준 기능으로 포함되어 있습니다. https://github.com/goktugyil/EZSwiftExtensions


답변