Einführung in Aufgabenwarteschlangen in Swift
Moderne mobile und Desktop-Anwendungen müssen schnell und reaktionsfähig sein. Wenn Sie schwere Berechnungen durchführen oder Daten aus dem Netzwerk direkt im Hauptthread laden, friert Ihre Anwendung ein und der Benutzer wird sie einfach schließen. Die Lösung sind Aufgabenwarteschlangen (queues).
In Swift (iOS/macOS) basiert die Verwaltung von Asynchronität auf drei Haupttechnologien: Grand Central Dispatch (GCD), Operation Queue und der modernen Syntax async/await. In diesem Artikel werden wir jede von Grund auf analysieren, Codebeispiele zeigen und erklären, wann was zu verwenden ist.
1. Grand Central Dispatch (GCD) und DispatchQueue
GCD ist eine Low-Level-Bibliothek von Apple zur Verwaltung der parallelen Ausführung von Code. Das Hauptelement ist DispatchQueue. Die Warteschlange führt Aufgaben (Closures) in der Reihenfolge ihrer Hinzufügung aus.
Arten von Warteschlangen
- Main Queue — serielle Warteschlange des Hauptthreads. Wird zum Aktualisieren der Benutzeroberfläche verwendet.
- Global Queues — parallele Warteschlangen mit unterschiedlichen Prioritäten (QoS:
.userInteractive,.userInitiated,.utility,.background). - Custom Queues — Ihre eigenen Warteschlangen (seriell oder parallel).
Beispiel: Ausführen einer Aufgabe im Hintergrund
import Foundation
// Asynchron in der HintergrundwarteschlangeDispatchQueue.global(qos: .background).async { // Schwere Arbeit (Laden, Datenverarbeitung) let result = performHeavyTask() // Ergebnis an den Hauptthread zurückgeben DispatchQueue.main.async { updateUI(with: result) }}
func performHeavyTask() -> String { Thread.sleep(forTimeInterval: 2) // Arbeit simulieren return "Fertig!"}
func updateUI(with text: String) { print("UI aktualisiert: \\(text)")}Beachten Sie: .async blockiert den aufrufenden Thread nicht. Wenn Sie auf das Ergebnis warten müssen, verwenden Sie .sync (rufen Sie jedoch niemals .sync vom Hauptthread aus auf — Sie erhalten einen Deadlock).
Beispiel: Serielle Warteschlange
let serialQueue = DispatchQueue(label: "com.example.serial")
serialQueue.async { print("Aufgabe 1")}serialQueue.async { print("Aufgabe 2")}// Ausgabe: Aufgabe 1, dann Aufgabe 22. Operation Queue — ein flexiblerer Ansatz
OperationQueue ist ein Wrapper über GCD, der eine objektorientierte Schnittstelle bietet. Sie erstellen eine Operation (oder BlockOperation), konfigurieren Abhängigkeiten und fügen sie zur Warteschlange hinzu.
Vorteile gegenüber GCD
- Abbrechen von Aufgaben (
cancel()) - Abhängigkeiten zwischen Aufgaben
- Statusüberwachung (isReady, isExecuting, isFinished)
- Maximale Anzahl paralleler Operationen
Beispiel: Grundlegende Verwendung
let operationQueue = OperationQueue()operationQueue.maxConcurrentOperationCount = 2 // nicht mehr als 2 Aufgaben gleichzeitig
let operation1 = BlockOperation { print("Daten laden...") Thread.sleep(forTimeInterval: 1)}
let operation2 = BlockOperation { print("Daten verarbeiten...") Thread.sleep(forTimeInterval: 1)}
// operation2 beginnt erst nach Abschluss von operation1operation2.addDependency(operation1)
operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)Beispiel: Operation abbrechen
let cancelableOp = BlockOperation { if !cancelableOp.isCancelled { print("Wichtige Arbeit ausführen") }}
operationQueue.addOperation(cancelableOp)
// Nach einiger Zeit abbrechenDispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { cancelableOp.cancel() print("Operation abgebrochen")}\