programing

iPhone - Grand Central Dispatch 메인 스레드

lovejava 2023. 6. 8. 19:06

iPhone - Grand Central Dispatch 메인 스레드

저는 성공적으로 앱에서 중앙 집중식 발송 기능을 사용해 왔지만, 다음과 같은 기능을 사용할 경우의 진정한 이점이 무엇인지 궁금했습니다.

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

아니 심지어는

dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff

즉, 두 경우 모두 메인 스레드에서 실행할 블록을 실행하는 것입니다. 정확히 앱이 실행되는 위치입니다. 이는 로드를 줄이는 데 도움이 되지 않습니다.첫 번째 경우에는 블록이 실행되는 시기를 제어할 수 없습니다.저는 당신이 블록을 발사한 지 0.5초 후에 블록이 실행되는 경우를 보았습니다.두 번째 경우는 다음과 유사합니다.

[self doStuff];

그렇죠?

여러분들은 어떻게 생각하시는지 궁금합니다.

블록을 주 대기열로 보내는 것은 일반적으로 백그라운드 대기열에서 수행되어 일부 백그라운드 처리가 완료되었음을 나타냅니다.

- (void)doCalculation
{
    //you can use any string instead "com.mycompany.myqueue"
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_async(backgroundQueue, ^{
        int result = <some really long calculation that takes seconds to complete>;

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateMyUIWithResult:result];
        });    
    });
}

이 경우 백그라운드 큐에서 장시간 계산을 수행하므로 계산이 완료되면 UI를 업데이트해야 합니다.UI 업데이트는 일반적으로 메인 큐에서 수행되어야 하므로 두 번째 중첩 dispatch_async를 사용하여 메인 큐로 '신호'를 다시 보냅니다.

기본 대기열로 다시 디스패치하려는 다른 예도 있을 수 있지만 일반적으로 이러한 방식으로 수행됩니다. 즉, 백그라운드 대기열로 디스패치되는 블록 내에서 네스트됩니다.

  • 백그라운드 처리 완료 -> UI 업데이트
  • 백그라운드 대기열에서 처리된 데이터 청크 -> 신호 주 대기열에서 다음 청크를 시작합니다.
  • 백그라운드 큐에서 수신 네트워크 데이터 -> 메시지가 도착했다는 신호 주 큐

기본 대기열에서 기본 대기열로 발송할 수 있는 이유에 대해 설명합니다.일반적으로 다음 번에 실행 루프에서 수행할 작업을 예약하기 위해 이 작업을 수행할 수는 있지만, 일반적으로 그렇게 하지는 않습니다.

스레드에서 주 대기열로 블록을 보내는 것이 유용할 수 있습니다.기본 대기열에서 대기 중인 다른 블록을 처리할 수 있으므로 다른 모든 블록을 단순히 실행하지 못하도록 차단할 수 있습니다.

예를 들어, 기본적으로 여러 개의 동시 연결을 처리하는 단일 스레드 서버를 작성할 수 있습니다.대기열의 개별 블록이 너무 오래 걸리지 않는 한, 서버는 새로운 요청에 계속 응답합니다.

만약 당신의 프로그램이 사건에 대응하는 데 평생을 보내는 것 외에는 아무것도 하지 않는다면, 이것은 매우 자연스러운 일이 될 수 있습니다.이벤트 핸들러가 메인 큐에서 실행되도록 설정한 다음 dispatch_main()을 호출하면 스레드 안전에 대해 전혀 걱정할 필요가 없을 수 있습니다.

dispatch_async와 dispatch_sync의 차이점을 알고 있다는 점에서 제가 당신의 질문을 올바르게 이해하고 있기를 바랍니다.

dispatch_async

블록을 비동기식으로 대기열로 전송합니다.즉, 블록을 큐로 보내고 메서드의 나머지 코드 실행을 계속하기 전에 반환될 때까지 기다리지 않습니다.

dispatch_sync

블록을 큐에 동기적으로 디스패치합니다.이렇게 하면 블록 실행이 완료될 때까지 메서드에 남아 있는 코드가 더 이상 실행되지 않습니다.

저는 주로 a를 사용했습니다.dispatch_async기본 대기열에서 작업을 수행하고 장치에 있는 추가 코어를 활용할 수 있습니다.그리고나서dispatch_asyncUI를 업데이트해야 하는 경우 메인 스레드로 이동합니다.

행운을 빌어요

긴 작업 전에 스피너를 설정하는 것과 같은 UI 작업에 유용한 한 가지 방법은 다음과 같습니다.

- (void) handleDoSomethingButton{

    [mySpinner startAnimating];

    (do something lengthy)
    [mySpinner stopAnimating];
}

긴 작업 중에 메인 스레드를 차단하고 UIKit가 실제로 스피너를 시작하지 못하도록 하기 때문에 작동하지 않습니다.

- (void) handleDoSomethingButton{
     [mySpinner startAnimating];

     dispatch_async (dispatch_get_main_queue(), ^{
          (do something lengthy)
          [mySpinner stopAnimating];
    });
}

제어를 실행 루프로 되돌립니다. 실행 루프는 UI 업데이트를 예약하고 스피너를 시작한 다음 실제 처리인 디스패치 대기열에서 다음 작업을 수행합니다.처리가 완료되면 애니메이션 중지가 호출되고 실행 루프로 돌아가 UI가 중지와 함께 업데이트됩니다.

스위프트 3, 4, 5

메인 스레드에서 실행 중인 코드

DispatchQueue.main.async {
    // Your code here
}

비동기는 비동기를 의미하며 대부분의 경우 비동기를 사용해야 합니다.메인 스레드에서 동기화를 호출하면 작업이 완료될 때까지 UI가 잠기므로 동기화를 호출하면 안 됩니다.Swift에서 이 작업을 수행하는 더 좋은 방법은 다음과 같습니다.

runThisInMainThread { () -> Void in
    // Run your code like this:
    self.doStuff()
}

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

내 레포에 표준 기능으로 포함되어 있으니 확인해 보세요. https://github.com/goktugyil/EZSwiftExtensions

언급URL : https://stackoverflow.com/questions/7905192/iphone-grand-central-dispatch-main-thread