Suche…


Syntax

  • Swift 3,0

  • DispatchQueue.main // Ruft die Hauptwarteschlange ab

  • DispatchQueue (Label: "my-serial-queue", Attribute: [.serial, .qosBackground]) // Erstellen Sie Ihre eigene private serielle Warteschlange

  • DispatchQueue.global (Attribute: [.qosDefault]) // Greifen Sie auf eine der globalen gleichzeitigen Warteschlangen zu

  • DispatchQueue.main.async {...} // Eine Task asynchron zum Hauptthread ausgeben

  • DispatchQueue.main.sync {...} // Eine Aufgabe synchron an den Haupt-Thread senden

  • DispatchQueue.main.asyncAfter (Deadline: .now () + 3) {...} // Sendet eine Task asynchron an den Haupt-Thread, der nach x Sekunden ausgeführt wird

  • Schnell <3,0

  • dispatch_get_main_queue () // Liefert die Hauptwarteschlange im Hauptthread

  • dispatch_get_global_queue (dispatch_queue_priority_t, 0) // Globale Warteschlange mit der angegebenen Priorität abrufen dispatch_queue_priority_t

  • dispatch_async (dispatch_queue_t) {() -> In ... ungültig machen} // Eine Aufgabe asynchron auf dem angegebenen dispatch_queue_t ausgeben

  • dispatch_sync (dispatch_queue_t) {() -> In ... ungültig machen} // Eine Aufgabe synchron auf dem angegebenen dispatch_queue_t ausgeben

  • dispatch_after (dispatch_time (DISPATCH_TIME_NOW, Int64 (Nanosekunden)), dispatch_queue_t, {...}); // Eine Aufgabe für den angegebenen dispatch_queue_t nach Nanosekunden ausgeben

Eine Grand Central Dispatch-Warteschlange (GCD) erhalten

Grand Central Dispatch arbeitet nach dem Konzept von "Dispatch Queues". Eine Versandwarteschlange führt die von Ihnen festgelegten Aufgaben in der Reihenfolge aus, in der sie übergeben werden. Es gibt drei Arten von Versandwarteschlangen:

  • Serial Dispatch Queues (auch als private Dispatch Queues bezeichnet) führen eine Aufgabe nacheinander aus. Sie werden häufig verwendet, um den Zugriff auf eine Ressource zu synchronisieren.
  • Concurrent Dispatch Queues (globale Dispatch Queues) führen eine oder mehrere Aufgaben gleichzeitig aus.
  • Die Main Dispatch Queue führt Aufgaben im Hauptthread aus.

So greifen Sie auf die Hauptwarteschlange zu:

3,0
let mainQueue = DispatchQueue.main
3,0
let mainQueue = dispatch_get_main_queue()

Das System stellt gleichzeitige globale Versandwarteschlangen (global für Ihre Anwendung) mit unterschiedlichen Prioritäten bereit. Sie können auf diese Warteschlangen mit der DispatchQueue Klasse in Swift 3 zugreifen:

3,0
let globalConcurrentQueue = DispatchQueue.global(qos: .default)

gleichwertig

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

In iOS 8 oder höher sind die möglichen Servicequalitätswerte möglicherweise .userInteractive , .userInitiated , .default , .utility und .background . Diese ersetzen die Konstanten DISPATCH_QUEUE_PRIORITY_ .

Sie können auch eigene Warteschlangen mit unterschiedlichen Prioritäten erstellen:

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)

In Swift 3 sind mit diesem Initialisierer erstellte Warteschlangen standardmäßig seriell. Durch die Weitergabe von .workItem für die Autorelease-Häufigkeit wird sichergestellt, dass für jedes Arbeitselement ein Autorelease-Pool erstellt und entleert wird. Es gibt auch .never , was bedeutet, dass Sie Ihre eigenen Autorelease-Pools selbst verwalten, oder .inherit , das die Einstellung von der Umgebung erbt. In den meisten Fällen verwenden Sie .never außer bei extremer Anpassung.

Ausführen von Aufgaben in einer Grand Central Dispatch-Warteschlange (GCD)

3,0

Verwenden Sie zum Ausführen von Aufgaben in einer Versandwarteschlange die Methoden sync , async und after .

So senden Sie eine Aufgabe asynchron in eine Warteschlange:

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

So senden Sie eine Aufgabe synchron in eine Warteschlange:

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

So senden Sie eine Aufgabe nach einer bestimmten Anzahl von Sekunden in eine Warteschlange:

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

HINWEIS: Alle Aktualisierungen der Benutzeroberfläche sollten im Hauptthread aufgerufen werden! Stellen Sie sicher, dass Sie den Code für UI-Aktualisierungen in DispatchQueue.main.async { ... } eingeben.

2,0

Warteschlangenarten:

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)

So senden Sie eine Aufgabe asynchron in eine Warteschlange:

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

So senden Sie eine Aufgabe synchron in eine Warteschlange:

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

Um eine Aufgabe nach einem Zeitintervall NSEC_PER_SEC (verwenden Sie NSEC_PER_SEC , um Sekunden in Nanosekunden umzuwandeln):

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
}

So führen Sie eine Task asynchron aus und aktualisieren die Benutzeroberfläche:

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

HINWEIS: Alle Aktualisierungen der Benutzeroberfläche sollten im Hauptthread aufgerufen werden! Stellen Sie sicher, dass Sie den Code für UI-Aktualisierungen in dispatch_async(dispatch_get_main_queue()) { ... } eingeben.

Gleichzeitige Schleifen

GCD stellt einen Mechanismus zum Durchführen einer Schleife bereit, wobei die Schleifen gleichzeitig in Bezug zueinander stattfinden. Dies ist sehr nützlich, wenn Sie eine Reihe von rechenintensiven Berechnungen durchführen.

Betrachten Sie diese Schleife:

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

Sie können diese Berechnungen gleichzeitig mit concurrentPerform (in Swift 3) oder dispatch_apply (in Swift 2) ausführen:

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
}

Der Schleifenschluss wird für jeden index von 0 bis einschließlich iterations aufgerufen. Diese Iterationen werden in Bezug zueinander gleichzeitig ausgeführt, und daher ist die Reihenfolge, in der sie ausgeführt werden, nicht garantiert. Die tatsächliche Anzahl von Iterationen, die zu einem bestimmten Zeitpunkt gleichzeitig ablaufen, wird im Allgemeinen durch die Fähigkeiten des betreffenden Geräts bestimmt (z. B. wie viele Kerne das Gerät hat).

Einige besondere Überlegungen:

  • concurrentPerform / dispatch_apply kann die Schleifen gleichzeitig ausführen, dies geschieht jedoch synchron mit dem Thread, von dem aus Sie es aufrufen. Rufen Sie das also nicht aus dem Haupt-Thread auf, da dieser den Thread blockiert, bis die Schleife abgeschlossen ist.

  • Da diese Schleifen gleichzeitig stattfinden, sind Sie für die Gewindesicherheit der Ergebnisse verantwortlich. Wenn Sie beispielsweise ein Wörterbuch mit den Ergebnissen dieser rechnerisch teuren Berechnungen aktualisieren, müssen Sie diese Aktualisierungen selbst synchronisieren.

  • Beachten Sie, dass das Ausführen von gleichzeitigen Schleifen mit einem gewissen Aufwand verbunden ist. Wenn die Berechnungen, die innerhalb der Schleife ausgeführt werden, nicht rechenintensiv sind, kann es vorkommen, dass die durch die Verwendung von gleichzeitigen Schleifen erzielte Leistung durch den mit der Synchronisierung all dieser gleichzeitigen Threads verbundenen Overhead verringert, wenn nicht vollständig versetzt wird.

    Sie sind also dafür verantwortlich, die richtige Menge an Arbeit zu bestimmen, die in jeder Iteration der Schleife ausgeführt werden muss. Wenn die Berechnungen zu einfach sind, können Sie "schreiten" verwenden, um mehr Arbeit pro Schleife hinzuzufügen. Anstatt eine gleichzeitige Schleife mit 1 Million trivialer Berechnungen durchzuführen, können Sie beispielsweise 100 Iterationen in Ihrer Schleife ausführen und 10.000 Berechnungen pro Schleife ausführen. Auf diese Weise wird für jeden Thread genügend Arbeit ausgeführt, sodass der mit der Verwaltung dieser gleichzeitigen Schleifen verbundene Aufwand geringer wird.

Ausführen von Aufgaben in einer OperationsQueue

Sie können sich eine OperationQueue als eine Reihe von Aufgaben vorstellen, die auf ihre Ausführung warten. Im Gegensatz zu Versandwarteschlangen in GCD sind Operationswarteschlangen kein FIFO (first-in-first-out). Stattdessen führen sie Aufgaben aus, sobald sie zur Ausführung bereit sind, sofern genügend Systemressourcen zur Verfügung stehen.

Holen Sie sich die OperationQueue :

3,0
let mainQueue = OperationQueue.main

Erstellen Sie eine benutzerdefinierte OperationQueue :

3,0
let queue = OperationQueue()
queue.name = "My Queue"
queue.qualityOfService = .default

Die Dienstqualität legt fest, wie wichtig die Arbeit ist oder wie sehr der Benutzer wahrscheinlich auf die unmittelbaren Ergebnisse der Aufgabe zählen wird.

Hinzufügen einer Operation zu einer OperationQueue :

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

queue.addOperation(operation)

Fügen Sie einer OperationQueue einen Block hinzu:

3,0
myQueue.addOperation {
    // some task
}

Mehrere Operation s zu einer OperationQueue :

3,0
let operations = [Operation]()
// Fill array with Operations

myQueue.addOperation(operations)

Passen Sie an, wie viele Operation gleichzeitig in der Warteschlange ausgeführt werden dürfen:

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

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

Durch das Anhalten einer Warteschlange wird verhindert, dass vorhandene, nicht gestartete Vorgänge oder neue, der Warteschlange hinzugefügte Vorgänge ausgeführt werden. isSuspended diese Warteschlange wieder aufzunehmen, setzen Sie isSuspended auf false :

3,0
myQueue.isSuspended = true

// Re-enable execution
myQueue.isSuspended = false

Durch das Anhalten einer OperationQueue Vorgänge, die bereits ausgeführt werden, nicht angehalten oder abgebrochen. Sie sollten nur versuchen, eine von Ihnen erstellte Warteschlange auszusetzen, keine globalen Warteschlangen oder die Hauptwarteschlange.

Erstellen von High-Level-Operationen

Das Foundation-Framework stellt den Operation bereit, der ein übergeordnetes Objekt darstellt, das einen Teil der Arbeit enthält, der in einer Warteschlange ausgeführt werden kann. Die Warteschlange koordiniert nicht nur die Leistung dieser Vorgänge, Sie können auch Abhängigkeiten zwischen Vorgängen einrichten, stornierbare Vorgänge erstellen, den Parallelitätsgrad der Vorgangswarteschlange einschränken usw.

Operation zur Ausführung bereit, wenn alle ihre Abhängigkeiten abgeschlossen sind. Die isReady Eigenschaft ändert sich dann in true .

Erstellen Sie eine einfache nicht gleichzeitig ablaufende Operation Unterklasse:

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
    }

}

Hinzufügen einer Operation zu einer OperationQueue :

1,0
myQueue.addOperation(operation)

Dadurch wird die Operation in der Warteschlange gleichzeitig ausgeführt.

Verwalten Sie Abhängigkeiten von einer Operation .

Abhängigkeiten definieren andere Operation , die in einer Warteschlange ausgeführt werden müssen, bevor der Operation als bereit zur Ausführung betrachtet wird.

1,0
operation2.addDependency(operation1)

operation2.removeDependency(operation1)

Ausführen einer Operation ohne Warteschlange:

1,0
   operation.start()

Abhängigkeiten werden ignoriert. Wenn dies ein gleichzeitiger Betrieb ist, kann immer noch die Aufgabe , gleichzeitig ausgeführt werden , wenn seine start Arbeit Hintergrund Warteschlangen auslagert.

Gleichzeitige Vorgänge.

Wenn die Aufgabe, die eine Operation ausführen soll, selbst asynchron ist (z. B. eine URLSession Datenaufgabe), sollten Sie die Operation als gleichzeitige Operation implementieren. In diesem Fall Ihre isAsynchronous sollte Implementierung zurückkehren true , Sie haben in der Regel eine start , die einige Setup ausführt, ruft dann seine main das die Aufgabe tatsächlich ausführt.

Zu Beginn der Implementierung einer asynchronen Operation müssen isFinished Methoden isExecuting , isFinished und KVO implementieren. Wenn die Ausführung startet, isExecuting Eigenschaft isExecuting in true . Wenn ein Operation seine Aufgabe beendet, wird isExecuting auf false und isFinished auf true . Wenn der Vorgang abgebrochen wird, ändern sich sowohl isCancelled als auch isFinished zu true . Alle diese Eigenschaften sind beobachtbar.

Operation abbrechen

Durch den Aufruf von cancel wird die isCancelled Eigenschaft einfach in true isCancelled . Um auf eine Stornierung aus Ihrer eigenen Operation Unterklasse zu antworten, sollten Sie den Wert von isCancelled mindestens einmal in main überprüfen und entsprechend reagieren.

1,0
operation.cancel()


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow