수색…


통사론

  • 스위프트 3.0

  • DispatchQueue.main // 메인 큐 얻기

  • DispatchQueue (label : "my-serial-queue", 속성 : [. serial], [.qosBackground]) // 자신 만의 비공개 시리얼 큐 생성

  • DispatchQueue.global (attributes : [.qosDefault]) // 전역 동시 대기열 중 하나에 액세스합니다.

  • DispatchQueue.main.async {...} // 주 스레드와 비동기 적으로 작업을 전달합니다.

  • DispatchQueue.main.sync {...} // 메인 스레드와 동시에 태스크를 디스패치합니다.

  • DispatchQueue.main.asyncAfter (deadline : .now () + 3) {...} // x 초 후에 실행될 주 스레드에 작업을 비동기 적으로 전달합니다.

  • 스위프트 <3.0

  • dispatch_get_main_queue () // 메인 쓰레드에서 실행중인 메인 큐를 얻는다.

  • dispatch_get_global_queue (dispatch_queue_priority_t, 0) // 지정된 우선 순위를 갖는 글로벌 큐 가져 오기 dispatch_queue_priority_t

  • dispatch_async (dispatch_queue_t) {() -> Void in ...} // 지정된 dispatch_queue_t에서 작업을 비동기 적으로 전달합니다.

  • dispatch_sync (dispatch_queue_t) {() -> Void in ...} // 지정된 dispatch_queue_t에서 작업을 동 기적으로 전송합니다.

  • dispatch_after (dispatch_time (DISPATCH_TIME_NOW, Int64 (나노초)), dispatch_queue_t, (...}); // 나노초 후에 지정한 dispatch_queue_t에서 작업을 전송합니다.

Grand Central Dispatch (GCD) 대기열 얻기

그랜드 센트럴 디스패치는 "디스패치 대기열"이라는 개념에서 작동합니다. 디스패치 대기열은 전달한 순서대로 지정한 작업을 실행합니다. 디스패치 대기열에는 세 가지 유형이 있습니다.

  • 직렬 디스패치 대기열 (일명 사설 디스패치 대기열)은 한 번에 하나의 작업을 순서대로 실행합니다. 리소스에 대한 액세스를 동기화하는 데 자주 사용됩니다.
  • 동시 디스패치 대기열 (일명 글로벌 디스패치 대기열)은 하나 이상의 작업을 동시에 실행합니다.
  • Main Dispatch Queue 는 주 스레드에서 작업을 실행합니다.

기본 대기열에 액세스하려면 다음을 수행하십시오.

3.0
let mainQueue = DispatchQueue.main
3.0
let mainQueue = dispatch_get_main_queue()

이 시스템은 우선 순위가 다양한 동시 전역 디스패치 대기열 (응용 프로그램에 전역)을 제공합니다. Swift 3의 DispatchQueue 클래스를 사용하여 이러한 대기열에 액세스 할 수 있습니다.

3.0
let globalConcurrentQueue = DispatchQueue.global(qos: .default)

~와 동등한

let globalConcurrentQueue = DispatchQueue.global()
3.0
let globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

iOS 8 이상에서 전달할 수있는 가능한 서비스 품질 값은 .userInteractive , .userInitiated , .default , .utility.background 입니다. 이것들은 DISPATCH_QUEUE_PRIORITY_ 상수를 대체합니다.

다양한 우선 순위를 사용하여 자체 대기열을 만들 수도 있습니다.

3.0
let myConcurrentQueue = DispatchQueue(label: "my-concurrent-queue", qos: .userInitiated, attributes: [.concurrent], autoreleaseFrequency: .workItem, target: nil)
let mySerialQueue = DispatchQueue(label: "my-serial-queue", qos: .background, attributes: [], autoreleaseFrequency: .workItem, target: nil)
3.0
let myConcurrentQueue = dispatch_queue_create("my-concurrent-queue", DISPATCH_QUEUE_CONCURRENT)
let mySerialQueue = dispatch_queue_create("my-serial-queue", DISPATCH_QUEUE_SERIAL)

Swift 3에서이 이니셜 라이저로 작성된 대기열은 기본적으로 직렬이며 autorelease 빈도로 .workItem 을 전달하면 자동 해제 풀이 생성되어 각 작업 항목에 대해 소모됩니다. 또한이 .never 당신이 당신의 자신의 오토 릴리즈 풀을 직접 관리, 또는 의미있는 .inherit 환경에서 설정을 상속한다. 대부분의 경우 극단적 인 사용자 지정을 제외하고는 .never 사용하지 않을 것입니다.

Grand Central Dispatch (GCD) 대기열에서 작업 실행

3.0

디스패치 대기열에서 작업을 실행하려면 sync , asyncafter 메서드를 사용합니다.

작업을 비동기 적으로 대기열에 보내려면 다음을 수행하십시오.

let queue = DispatchQueue(label: "myQueueName")

queue.async {
    //do something
    
    DispatchQueue.main.async {
        //this will be called in main thread
        //any UI updates should be placed here
    }
}
// ... code here will execute immediately, before the task finished

작업을 동 기적으로 대기열로 보내려면 다음을 수행하십시오.

queue.sync {
    // Do some task
}
// ... code here will not execute until the task is finished

특정 시간 (초) 후에 작업을 대기열로 보내려면 다음을 수행하십시오.

queue.asyncAfter(deadline: .now() + 3) {
    //this will be executed in a background-thread after 3 seconds
}
// ... code here will execute immediately, before the task finished

참고 : 사용자 인터페이스의 모든 업데이트는 주 스레드에서 호출해야합니다! DispatchQueue.main.async { ... } 에 UI 업데이트 코드를 넣었는지 확인하십시오.

2.0

대기열 유형 :

let mainQueue = dispatch_get_main_queue()
let highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
let backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)

작업을 비동기 적으로 대기열에 보내려면 다음을 수행하십시오.

dispatch_async(queue) {
    // Your code run run asynchronously. Code is queued and executed 
    // at some point in the future.
}
// Code after the async block will execute immediately

작업을 동 기적으로 대기열로 보내려면 다음을 수행하십시오.

dispatch_sync(queue) {
    // Your sync code
}
// Code after the sync block will wait until the sync task finished

시간 간격 후에 작업을 보내려면 ( NSEC_PER_SEC 를 사용하여 초 단위를 나노초로 변환)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
    // Code to be performed in 2.5 seconds here
}

비동기 적으로 작업을 실행하고 UI를 업데이트하려면 다음을 수행하십시오.

dispatch_async(queue) {
    // Your time consuming code here
    dispatch_async(dispatch_get_main_queue()) {
        // Update the UI code 
    }
}

참고 : 사용자 인터페이스의 모든 업데이트는 주 스레드에서 호출해야합니다! dispatch_async(dispatch_get_main_queue()) { ... } 에 UI 업데이트 코드를 넣었는지 확인하십시오.

동시 루프

GCD는 루프를 수행하는 메커니즘을 제공하여 루프가 서로 관련하여 동시에 발생합니다. 이것은 일련의 계산 비용이 많이 드는 계산을 수행 할 때 매우 유용합니다.

이 루프를 생각해보십시오.

for index in 0 ..< iterations {
    // Do something computationally expensive here
}

concurrentPerform (Swift 3) 또는 dispatch_apply (Swift 2)를 사용하여 이러한 계산을 동시에 수행 할 수 있습니다.

3.0
DispatchQueue.concurrentPerform(iterations: iterations) { index in
    // Do something computationally expensive here
}
3.0
dispatch_apply(iterations, queue) { index in
    // Do something computationally expensive here
}

루프 클로저는 0 부터 시작하여 iterations 포함하지 않는 각 index 에 대해 호출됩니다. 이러한 반복은 서로에 대해 동시에 실행되므로 실행 순서가 보장되지 않습니다. 주어진 시간에 동시에 발생하는 반복의 실제 횟수는 일반적으로 해당 장치의 기능 (예 : 장치의 코어 수)에 따라 결정됩니다.

몇 가지 특별한 고려 사항 :

  • concurrentPerform / dispatch_apply 는 서로에 대해 루프를 동시에 실행할 수 있지만이 모든 것은 호출하는 스레드와 관련하여 동 기적으로 발생합니다. 따라서 메인 스레드에서 호출하지 마십시오. 루프가 완료 될 때까지 해당 스레드가 차단됩니다.

  • 이러한 루프는 서로에 대해 동시에 발생하기 때문에 결과의 스레드 안전성을 보장해야합니다. 예를 들어 계산에 비용이 많이 드는 계산 결과로 사전을 업데이트하는 경우 이러한 업데이트를 직접 동기화해야합니다.

  • 동시 루프 실행과 관련하여 약간의 오버 헤드가 있습니다. 따라서 루프 내에서 수행되는 계산이 계산 집약적이지 않은 경우 동시 루프를 사용하여 얻은 성능이 완전히 상쇄되지는 못하더라도 이러한 모든 동시 스레드를 동기화하는 데 소요되는 오버 헤드로 인해 줄어들 수 있습니다.

    따라서 반복문을 반복 할 때마다 수행 할 정확한 작업량을 결정해야합니다. 계산이 너무 단순하다면 "striding"을 사용하여 루프 당 더 많은 작업을 포함시킬 수 있습니다. 예를 들어, 100 만 개의 사소한 계산으로 동시 루프를 수행하는 대신 루프 당 100 회 반복 수행하여 루프 당 10,000 회 계산을 수행 할 수 있습니다. 이렇게하면 각 스레드에서 충분한 작업이 수행되므로 이러한 동시 루프를 관리하는 데 따른 오버 헤드가 덜 중요 해집니다.

OperationQueue에서 작업 실행

OperationQueue 는 실행 대기중인 작업 라인으로 생각할 수 있습니다. GCD의 디스패치 대기열과 달리 작업 대기열은 선입 선출 (FIFO)이 아닙니다. 대신, 그들은 그것을 수행 할 수있는 충분한 시스템 자원이있는 한, 실행 준비가 되 자마자 작업을 실행합니다.

메인 OperationQueue :

3.0
let mainQueue = OperationQueue.main

사용자 지정 OperationQueue 만들기 :

3.0
let queue = OperationQueue()
queue.name = "My Queue"
queue.qualityOfService = .default

서비스 품질은 작업의 중요성 또는 작업에서 즉각적인 결과에 대한 사용자의 예상 가능성을 지정합니다.

추가 OperationOperationQueue :

3.0
// An instance of some Operation subclass
let operation = BlockOperation {
    // perform task here
}

queue.addOperation(operation)

OperationQueue 블록 추가 :

3.0
myQueue.addOperation {
    // some task
}

여러 추가 Operation 에들 OperationQueue :

3.0
let operations = [Operation]()
// Fill array with Operations

myQueue.addOperation(operations)

대기열 내에서 동시에 실행될 수있는 Operation 수 조정 :

myQueue.maxConcurrentOperationCount = 3 // 3 operations may execute at once

// Sets number of concurrent operations based on current system conditions
myQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount

대기열을 일시 중단하면 기존의 시작되지 않은 조작 또는 대기열에 추가 된 새로운 조작의 실행을 시작할 수 없습니다. 이 큐를 재개하는 방법은 isSuspended 다시 false 로 설정하는 isSuspended .

3.0
myQueue.isSuspended = true

// Re-enable execution
myQueue.isSuspended = false

OperationQueue 일시 중단해도 이미 실행중인 작업이 중지되거나 취소되지 않습니다. 하나는 글로벌 대기열이나 기본 대기열이 아닌 작성한 대기열을 일시 중단해야합니다.

고급 작업 만들기

Foundation 프레임 워크는 큐에서 실행될 수있는 작업의 일부를 캡슐화하는 상위 수준의 개체를 나타내는 Operation 유형을 제공합니다. 대기열은 이러한 작업의 성능을 조정할뿐만 아니라 작업간에 종속성을 설정하고 취소 가능한 작업을 생성하고 작업 대기열에서 사용하는 동시성의 수준을 제한 할 수 있습니다.

Operation 은 모든 종속성이 완료되면 실행 준비가됩니다. 그러면 isReady 속성이 true 로 변경됩니다.

간단한 비 동시성 Operation 서브 클래스 만들기 :

3.0
class MyOperation: Operation {

    init(<parameters>) {
        // Do any setup work here
    }

    override func main() {
        // Perform the task
    }

}
2.3
class MyOperation: NSOperation {

    init(<parameters>) {
        // Do any setup work here
    }

    override func main() {
        // Perform the task
    }

}

OperationQueue 연산을 추가합니다.

1.0
myQueue.addOperation(operation)

그러면 대기열에서 동시에 작업이 실행됩니다.

Operation 에 대한 종속성을 관리합니다.

종속성은 해당 Operation 이 실행 준비가 완료되기 전에 대기열에서 실행해야하는 다른 Operation 정의합니다.

1.0
operation2.addDependency(operation1)

operation2.removeDependency(operation1)

대기열없이 Operation 실행 :

1.0
   operation.start()

종속성은 무시됩니다. 동시 작업이면 start 메소드 오프로드가 백그라운드 대기열로 작동하면 작업이 동시에 실행될 수 있습니다.

동시 운영.

Operation 이 수행해야 할 Operation 이 그 자체로 비동기 (예 : URLSession 데이터 타스크) 인 경우 Operation 을 동시 조작으로 구현해야합니다. 이 경우 isAsynchronous 구현은 true 를 반환해야 true . 일반적으로 몇 가지 설정을 수행하는 start 메서드가 있고 실제로 작업을 실행하는 main 메서드가 호출됩니다.

비동기 Operation 구현 isExecuting , isFinished 메서드 및 KVO를 구현해야합니다. 따라서 실행이 시작되면 isExecuting 속성이 true 변경됩니다. 작업이 Operation 완료하면 isExecutingfalse 로 설정되고 isFinishedtrue 로 설정됩니다. 작업이 모두 취소되는 경우 isCancelledisFinished 로 변경 true . 이러한 모든 속성은 키 - 값 관찰 가능합니다.

Operation 취소하십시오.

cancel 호출하면 isCancelled 속성이 true 변경됩니다. 자신 내에서 취소에 대응하기 위해 Operation 서브 클래스, 당신의 가치 확인해야합니다 isCancelled 적어도 주기적으로 내 main 적절하게 반응한다.

1.0
operation.cancel()


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