수색…


소개

관련 항목 : 그랜드 센트럴 디스패치

통사론

  • dispatch_async - 별도의 대기열에서 코드 블록을 실행하고 현재 대기열을 중지하지 않습니다. 큐가 dispatch_async가 호출 된 스레드와 다른 스레드에 있으면 dispatch_async가 실행되는 동안 코드가 실행되는 동안 블록의 코드가 실행됩니다.
  • dispatch_sync는 - 개별 큐 코드의 블록을 실행하고, 현재 큐를 중지 않는다. 큐가 dispatch_async가 호출 된 스레드와 다른 스레드에 있으면 블록의 코드가 실행되고 메서드가 호출 된 스레드의 실행은 스레드가 완료된 후에 다시 시작됩니다

매개 변수

디스패치 블록의 코드가 실행될 입니다. 는 스레드와 비슷하지만 정확히 같은 것은 아닙니다. 서로 다른 큐의 코드를 병렬로 실행할 수 있습니다. dispatch_get_main_queue 를 사용하여 주 스레드의 대기열을 확보하십시오. 새로운 대기열을 작성하고 새로운 스레드를 작성하려면 dispatch_queue_create("QUEUE_NAME", DISPATCH_QUEUE_CONCURRENT) . 첫 번째 매개 변수는 대기열의 이름입니다.이 대기열은 블록이 실행 중일 때 일시 중지하면 디버거에 표시됩니다. 두 번째 매개 변수는 여러 개의 dispatch_async 또는 dispatch_sync 호출에 대해 동일한 대기열을 사용하지 않는 한 중요하지 않습니다. 다른 블록이 동일한 대기열에있을 때 어떤 일이 발생하는지 설명합니다. DISPATCH_QUEUE_CONCURRENT 는 두 블록을 동시에 실행하게하며 DISPATCH_QUEUE_SERIAL 은 두 번째 블록이 첫 번째 블록이 완료 될 때까지 대기하게합니다
블록 이 블록의 코드는 큐 queue 에서 실행 queue . 여기에서 별도의 큐에 실행할 코드를 넣으십시오. 유용한 팁 : Xcode에이 글을 쓰고 있는데, 블록 인자의 주위에 파란 윤곽선이 있다면 인수를 더블 클릭하면 Xcode가 자동으로 빈 블럭을 만들 것입니다 (이것은 모든 함수 또는 메소드의 모든 블럭 인수에 적용됩니다)

비고

대기열을 사용할 때 발생하는 별도의 스레드에서 작업 할 때마다 스레드 안전을 유지하는 것이 중요합니다. 일부 메소드, 특히 UIView 용 메소드는 주 스레드가 아닌 다른 스레드에서 작동하지 않을 수도 있습니다. 또한 변경 사항을 고려하지 않는 한 주 스레드에서 사용되고있는 변수 (속성, 속성 등)를 변경하지 않도록하십시오.

동시에 코드 실행 - 다른 코드를 실행하면서 코드 실행

뭔가 다른 일을하면서 ( "Bar"로깅) 행동하면서 (이 경우에는 "Foo"로깅) 수행하고 싶다고합시다. 일반적으로 동시성을 사용하지 않으면 이러한 작업 중 하나가 완전히 실행되고 다른 작업은 완전히 완료된 후에 만 ​​실행됩니다. 하지만 병행 성을 사용하면 두 작업을 동시에 실행할 수 있습니다.

dispatch_async(dispatch_queue_create("Foo", DISPATCH_QUEUE_CONCURRENT), ^{
    for (int i = 0; i < 100; i++) {
        NSLog(@"Foo");
        usleep(100000);
    }
});

for (int i = 0; i < 100; i++) {
    NSLog(@"Bar");
    usleep(50000);
}

이것은 "Foo"를 100 번 기록 할 것이고, 기록 할 때마다 100ms 동안 일시 정지 할 것입니다. 그러나 이것은 모든 것을 별도의 스레드에서 할 것입니다. Foo 가 로그되는 동안 "Bar"도 50ms 간격으로 동시에 기록됩니다. "Foo"와 "Bars"를 함께 섞어 출력하는 것이 이상적입니다.

메인 스레드에서 실행 중

비동기 적으로 작업을 수행 할 때 일반적으로 코드가 메인 스레드에서 실행되도록해야합니다. 예를 들어 REST API를 비동기 적으로 실행하려고 할 수 있지만 화면에 UILabel에 결과를 넣을 수 있습니다. UILabel을 업데이트하기 전에 코드가 주 스레드에서 실행되는지 확인해야합니다.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //Perform expensive tasks
    //...

    //Now before updating the UI, ensure we are back on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        label.text = //....
    });
}

화면의 뷰를 업데이트 할 때마다 항상 주 스레드에서 수행해야합니다. 그렇지 않으면 정의되지 않은 동작이 발생할 수 있습니다.

디스패치 그룹 - 완료된 다른 스레드를 기다립니다.

dispatch_group_t preapreWaitingGroup = dispatch_group_create();

dispatch_group_enter(preapreWaitingGroup);
[self doAsynchronousTaskWithComplete:^(id someResults, NSError *error) { 
    // Notify that this task has been completed.
    dispatch_group_leave(preapreWaitingGroup);  
}]

dispatch_group_enter(preapreWaitingGroup);
[self doOtherAsynchronousTaskWithComplete:^(id someResults, NSError *error) { 
    dispatch_group_leave(preapreWaitingGroup);  
}]

dispatch_group_notify(preapreWaitingGroup, dispatch_get_main_queue(), ^{
    // This block will be executed once all above threads completed and call dispatch_group_leave
    NSLog(@"Prepare completed. I'm readyyyy");
});

업데이트 1. Swift 3 버전.

let prepareGroup = DispatchGroup()
prepareGroup.enter()
doAsynchronousTaskWithComplete() { (someResults, error) in
    // Notify that this task has been completed.
    prepareGroup.leave()
}

prepareGroup.enter()
doOtherAsynchronousTaskWithComplete() { (someResults, error) in
    // Notify that this task has been completed.
    prepareGroup.leave()
}

prepareGroup.notify(queue: DispatchQueue.main) {
    // This block will be executed once all above threads completed and call dispatch_group_leave
    print("Prepare completed. I'm readyyyy")
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow