Zoeken…


Invoering

Gerelateerde onderwerpen:

Grand Central verzending

samenloop

Invoering

Stel dat je meerdere threads hebt. Elke thread voert één taak uit. U wilt een melding ontvangen op de mainThread OF een andere thread, wanneer alle taak-threads zijn voltooid.

De eenvoudigste oplossing voor een dergelijk probleem is een DispatchGroup .

Wanneer u een DispatchGroup , enter u voor elke aanvraag de groep in en voor elke voltooide aanvraag leave de groep.

Wanneer er geen aanvragen meer in de groep zijn, wordt u hiervan op de notify (gemeld).


Gebruik:

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

Met het bovenstaande hoeft u niet oneindig te wait tot alle taken zijn voltooid. U kunt een lader weergeven VOORDAT alle taken zijn gestart en de lader sluiten NADAT alle taken zijn voltooid. Op deze manier wordt uw hoofdthread niet geblokkeerd en blijft uw code schoon.

Stel nu dat u ook wilt dat de taken worden ordered of voeg hun antwoorden achtereenvolgens toe aan een array. Je zou het volgende kunnen doen:

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

Notes

Elk item moet een exit hebben in een DispatchGroup . Als je vergeet te leave na entering , ben je jezelf aan het instellen. U ontvangt NOOIT een melding wanneer de taken zijn voltooid.

Het aantal enter moet gelijk zijn aan het aantal leave .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow