Ricerca…


introduzione

Argomenti correlati:

Grand Central Dispatch

Concorrenza

introduzione

Supponiamo che tu abbia più thread in esecuzione. Ogni thread sta facendo un compito. Si desidera ricevere una notifica sul mainThread OPPURE su un altro thread, una volta completati tutti i thread delle attività.

La soluzione più semplice a tale problema è un DispatchGroup .

Quando si utilizza un gruppo DispatchGroup , per ogni richiesta, si enter nel gruppo e per ogni richiesta completata si leave dal gruppo.

Quando non ci sono più richieste nel gruppo, sarai notify (notificato).


Uso:

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

Con quanto sopra, non è necessario wait all'infinito finché tutte le attività sono state completate. È possibile visualizzare un caricatore PRIMA di iniziare tutte le attività e chiudere il caricatore DOPO che tutte le attività sono state completate. In questo modo, il tuo thread principale non viene bloccato e il tuo codice rimane pulito.

Supponiamo ora che vogliate anche ordered i compiti o aggiungere le loro risposte a un array in sequenza. Potresti fare quanto segue:

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

Gli appunti

Ogni voce deve avere un'uscita in un DispatchGroup . Se ti dimentichi di leave dopo essere entering , ti stai preparando. Non sarai mai informato quando le attività saranno completate.

L'importo di enter deve essere uguale all'importo del leave .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow