Suche…


Einführung

Verwandte Themen:

Grand Central Dispatch

Parallelität

Einführung

Angenommen, Sie haben mehrere Threads, die ausgeführt werden. Jeder Thread erledigt eine Aufgabe. Sie möchten entweder im mainThread ODER einem anderen Thread benachrichtigt werden, wenn alle Task-Threads abgeschlossen sind.

Die einfachste Lösung für ein solches Problem ist eine DispatchGroup .

Bei der Verwendung von DispatchGroup , für jede Anforderung, Sie enter die Gruppe und für jede abgeschlossene Anforderung, Sie leave die Gruppe.

Wenn keine Anforderungen mehr in der Gruppe vorhanden sind, werden Sie notify (benachrichtigt).


Verwendungszweck:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        let dispatchGroup = DispatchGroup() //Create a group for the tasks.
        let session: URLSession = URLSession.shared
        
        dispatchGroup.enter() //Enter the group for the first task.
        
        let firstTask = session.dataTask(with: URLRequest(url: URL(string: "https://stackoverflow.com")!)) { (data, response, error) in
            
            //Process Response..
            
            dispatchGroup.leave() //Leave the group for the first task.
        }

        
        dispatchGroup.enter()  //Enter the group for the second task.
        
        let secondTask = session.dataTask(with: URLRequest(url: URL(string: "https://google.ca")!)) { (data, response, error) in
            
            //Process Response..
            
            dispatchGroup.leave()  //Leave the group for the second task.
        }
        
        
        //Get notified on the main thread/queue.. when ALL of the tasks above has been completed.
        dispatchGroup.notify(queue: DispatchQueue.main) { 
            
            print("Every task is complete")
            
        }
        
        
        //Start the tasks.
        firstTask.resume()
        secondTask.resume()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

Mit dem oben genannten müssen Sie nicht unendlich lange wait bis alle Aufgaben abgeschlossen sind. Sie können einen Loader anzeigen, BEVOR alle Tasks gestartet sind und den Loader BEENDEN, nachdem alle Tasks abgeschlossen sind. Auf diese Weise wird Ihr Haupt-Thread nicht blockiert und Ihr Code bleibt sauber.

Nehmen Sie nun an, Sie möchten auch, dass die Aufgaben ordered oder fügen Sie die Antworten nacheinander in ein Array ein. Sie könnten folgendes tun:

import UIKit

//Locking mechanism..
func synchronized(_ lock: AnyObject, closure: () -> Void) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}

class ViewController: UIViewController {

    let lock = NSObject() //Object to lock on.
    var responseArray = Array<Data?>() //Array of responses.
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let dispatchGroup = DispatchGroup()
        let session: URLSession = URLSession.shared
        
        dispatchGroup.enter() //Enter the group for the first task.
        
        let firstTask = session.dataTask(with: URLRequest(url: URL(string: "https://stackoverflow.com")!)) { (data, response, error) in
            
            //Process Response..

            synchronized(self.lock, closure: { () -> Void in
                self.responseArray[0] = data ?? nil
            })

            dispatchGroup.leave() //Leave the group for the first task.
        }

        
        dispatchGroup.enter()  //Enter the group for the second task.
        
        let secondTask = session.dataTask(with: URLRequest(url: URL(string: "https://google.ca")!)) { (data, response, error) in
            
            //Process Response..
            
            synchronized(self.lock, closure: { () -> Void in
                self.responseArray[1] = data ?? nil
            })
            
            dispatchGroup.leave()  //Leave the group for the second task.
        }
        
        
        //Get notified on the main thread.. when ALL of the requests above has been completed.
        dispatchGroup.notify(queue: DispatchQueue.main) { 
            
            print("Every task is complete..")
            
            for i in 0..<self.responseArray.count {
                
                if self.responseArray[i] == nil {
                    print("Request #\(i) Failed.\n")
                }
                else {
                    print("Request #\(i) Succeeded.\n")
                }
            }
        }
        
        //Two tasks added to the array. Responses are assumed nil until they complete.
        self.responseArray.append(nil)
        self.responseArray.append(nil)
        
        //Start the tasks.
        firstTask.resume()
        secondTask.resume()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

Anmerkungen

Jeder Eintrag muss einen Ausgang in einer DispatchGroup . Wenn Sie nach dem entering vergessen zu leave , richten Sie sich ein. Sie werden NIEMALS benachrichtigt, wenn die Aufgaben abgeschlossen sind.

Der Betrag für die enter muss der Höhe des leave .



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