サーチ…


構文

  • スウィフト3.0

  • DispatchQueue.main //メインキューを取得する

  • DispatchQueue(ラベル: "my-serial-queue"、属性:[.serial、.qosBackground])//独自のプライベートシリアルキューを作成する

  • DispatchQueue.global(attributes:[.qosDefault])//グローバル並行キューにアクセスする

  • DispatchQueue.main.async {...} //タスクをメインスレッドに非同期にディスパッチします

  • DispatchQueue.main.sync {...} //メインスレッドに同期してタスクをディスパッチします

  • DispatchQueue.main.asyncAfter(期限:.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)キューの取得

グランドセントラルディスパッチは、「ディスパッチキュー」の概念に基づいて動作します。ディスパッチ・キューは、指定したタスクを渡された順序で実行します。ディスパッチキューには3つのタイプがあります。

  • シリアルディスパッチキュー (別名プライベートディスパッチキュー)は、一度に1つのタスクを順に実行します。リソースへのアクセスを同期させるために頻繁に使用されます。
  • 並行ディスパッチキュー (別名グローバルディスパッチキュー)は、1つ以上のタスクを同時に実行します。
  • メインディスパッチキューは、メインスレッド上でタスクを実行します。

メインキューにアクセスするには:

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

ディスパッチキューでタスクを実行するには、 syncasync 、およびafterメソッドを使用します。

タスクを非同期でキューにディスパッチするには:

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アップデート用のコードを記述していることを確認してくださいDispatchQueue.main.async { ... }

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 
    }
}

注:ユーザーインターフェイスの更新は、メインスレッドで呼び出す必要があります! UIアップデートのコードをdispatch_async(dispatch_get_main_queue()) { ... }中に入れて、

並行ループ

GCDは、ループを実行するためのメカニズムを提供します。これにより、ループは互いに対して同時に発生します。これは、一連の計算コストの高い計算を実行する場合に非常に便利です。

このループを考えてみましょう。

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

concurrentPerform (Swift 3)またはdispatch_apply (Swift 2)を使用concurrentPerform 、これらの計算を同時に実行できます。

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に対して呼び出されiterations 。これらの反復は、互いに並行して実行されるため、実行される順序は保証されません。任意の時点で同時に発生する実際の反復回数は、一般に、対象のデバイスの能力(例えば、デバイスのコア数)によって決まります。

特別な考慮事項のいくつか:

  • concurrentPerform / dispatch_applyはループを互いに対して同時に実行するかもしれませんが、これはすべてあなたが呼び出すスレッドに関して同期的に起こります。したがって、ループが完了するまで、スレッドをブロックするので、メインスレッドからこれを呼び出さないでください。

  • これらのループは互いに並行して実行されるため、結果のスレッド安全性を保証する責任があります。たとえば、計算コストの高い計算結果を使用して辞書を更新する場合は、それらの更新を自分で同期させてください。

  • 並行ループの実行にはいくつかのオーバーヘッドが関係していることに注意してください。したがって、ループ内で実行される計算の計算量が十分でない場合、並行ループを使用して得られたすべてのパフォーマンスは、完全に相殺されないと、これらの同時スレッドの同期に関連するオーバーヘッドによって減少する可能性があります。

    したがって、ループの各反復で実行される正しい作業量を決定するのは、担当者の責任です。計算が単純すぎる場合は、ループごとにもっと多くの作業を含めるために "ストライド"を使用することができます。たとえば、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

Quality of Serviceは、作業の重要性、またはタスクからの即時の結果をユーザーがどれだけ評価するかを指定します。

追加OperationするOperationQueue

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にSを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

キューを一時停止すると、既存の起動されていない操作やキューに追加された新しい操作の実行が開始されなくなります。このキューを再開する方法は、 isSuspendedfalse戻すことです。

3.0
myQueue.isSuspended = true

// Re-enable execution
myQueue.isSuspended = false

OperationQueue一時停止しても、すでに実行中の操作は停止またはキャンセルされません。グローバルキューやメインキューではなく、作成したキューを一時停止する必要があります。

高レベル操作の作成

Foundationフレームワークは、キュー上で実行される可能性のある作業の一部をカプセル化する高水準オブジェクトを表すOperation型を提供します。キューはこれらの操作のパフォーマンスを調整するだけでなく、操作間の依存関係を確立したり、取り消し可能な操作を作成したり、操作キューによって使用される並行性の程度を制限したりすることもできます。

Operation 、すべての依存関係の実行が終了した時点で実行可能になります。 isReadyプロパティはtrue変わり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が実行するタスクがそれ自体では非同期(例: URLSessionデータタスク)である場合、 Operationを並行操作として実装する必要があります。この場合、 isAsynchronous実装はtrueを返す必要があります。通常、いくつかの設定を実行するstartメソッドがあり、実際にタスクを実行するmainメソッドが呼び出されます。

非同期Operation実装を開始するときは、 isExecutingisFinishedメソッドおよびKVOを実装する必要があります。したがって、実行が開始されると、 isExecutingプロパティがtrue変更されtrue 。ときOperationそのタスクを終了し、 isExecutingに設定されているfalse 、そしてisFinishedに設定されているtrue 。操作は、それが両方のキャンセルされた場合isCancelledisFinishedに変更true 。これらのプロパティはすべてキー値で観測可能です。

Operation

cancel呼び出すと、 isCancelledプロパティがtrue変更されtrue 。あなた自身のOperationサブクラス内からのキャンセルに応答するには、少なくともmain内のisCancelledの値を定期的にチェックし、適切に応答する必要があります。

1.0
operation.cancel()


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow