Zoeken…


Invoering

Grand Central Dispatch (GCD) is het antwoord van Apple op multithreading. Het is een lichtgewicht framework voor het synchroon of asynchroon uitvoeren van taken in wachtrijen en verwerkt CPU-threads achter de schermen.

Gerelateerd onderwerp: Concurrency

Maak een verzendwachtrij

U kunt uw eigen wachtrij maken met dispatch_queue_create

Doelstelling C

dispatch_queue_t queue = dispatch_queue_create("com.example.myqueue",  DISPATCH_QUEUE_SERIAL);

Snel

// Before Swift 3
let queue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL)
// Swift 3
let queue = DispatchQueue(label: "com.example.myqueue") //default is serial queue, unless .concurrent is specified as an attribute otherwise

De hoofdwachtrij verkrijgen

De hoofdwachtrij is de verzendwachtrij waarin alle UI-updates plaatsvinden en de code met wijzigingen in de UI wordt geplaatst.

U moet naar de NSURLSession gaan om de UI bij te werken na voltooiing van een asynchroon proces zoals NSURLSession

Er zijn twee soorten hoofdwachtrijen synchronous en asynchronous . Wanneer u iets synchronously , betekent dit dat de thread die de bewerking heeft gestart, wacht totdat de taak is voltooid voordat deze wordt voortgezet. Asynchronous betekent dat het niet zal wachten.

Code doelstelling-C

Synchronous hoofdwachtrijoproep

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

Asynchronous hoofdwachtrijoproep

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here to Usually to update the User Interface
});

SWIFT 3

Asynchronous hoofdwachtrijoproep

DispatchQueue.main.async {

}

Synchronous hoofdwachtrijoproep

DispatchQueue.main.sync {

}

Verzendgroep

DispatchGroup zorgt voor geaggregeerde synchronisatie van werk. U kunt ze gebruiken om meerdere verschillende werkitems in te dienen en bij te houden wanneer ze allemaal zijn voltooid, ook al kunnen ze in verschillende wachtrijen worden uitgevoerd. Dit gedrag kan nuttig zijn als er geen vooruitgang kan worden geboekt totdat alle opgegeven taken zijn voltooid.

Een scenario waarin dit nuttig kan zijn, is als u meerdere webservice-oproepen hebt die allemaal moeten worden voltooid voordat u doorgaat. U moet bijvoorbeeld meerdere sets gegevens downloaden die door een bepaalde functie moeten worden verwerkt. U moet wachten tot alle webservices zijn voltooid voordat u de functie aanroept om alle ontvangen gegevens te verwerken.

Swift 3

func doLongTasksAndWait () {
    print("starting long running tasks")
    let group = DispatchGroup()          //create a group for a bunch of tasks we are about to do
    for i in 0...3 {                     //launch a bunch of tasks (eg a bunch of webservice calls that all need to be finished before proceeding to the next ViewController)
        group.enter()                    //let the group know that something is being added
        DispatchQueue.global().async {   //run tasks on a background thread
            sleep(arc4random() % 4)      //do some long task eg webservice or database lookup (here we are just sleeping for a random amount of time for demonstration purposes)
            print("long task \(i) done!")
            group.leave()                //let group know that the task is finished
        }
    }
    group.wait()                         //will block whatever thread we are on here until all the above tasks have finished (so maybe dont use this function on your main thread)
    print("all tasks done!")
}

Als u niet wilt wachten tot de groepen zijn voltooid, maar in plaats daarvan een functie wilt uitvoeren nadat alle taken zijn voltooid, gebruikt u de notify in plaats van de group.wait()

group.notify(queue: DispatchQueue.main) { //the queue: parameter is which queue this block will run on, if you need to do UI updates, use the main queue
    print("all tasks done!")              //this will execute when all tasks have left the group
}

Voorbeelduitgang:

starting long running tasks
long task 0 done!
long task 3 done!
long task 1 done!
long task 2 done!
all tasks done!

Raadpleeg voor meer informatie de Apple Docs of het verwante onderwerp

Verzending Semafoor

DispatchSemaphore biedt een efficiënte implementatie van een traditionele tellende semafoor, die kan worden gebruikt om de toegang tot een resource in meerdere uitvoeringscontexten te beheren.

Een scenario voor wanneer u een semafoor gebruikt, kan zijn als u wat bestanden leest / schrijft, als meerdere taken tegelijkertijd proberen te lezen en uit een bestand te schrijven, het uw prestaties zou kunnen verhogen om elke taak op zijn beurt te laten wachten, zodat om de I / O-controller niet te overbelasten.

Swift 3

func do2TasksAtATime () {
    print("starting long running tasks (2 at a time)")
    let sem = DispatchSemaphore(value: 2)            //this semaphore only allows 2 tasks to run at the same time (the resource count)
    for i in 0...7 {                                 //launch a bunch of tasks
        DispatchQueue.global().async {               //run tasks on a background thread
            sem.wait()                               //wait here if no resources available
            sleep(2)                                 //do some long task eg file access (here we are just sleeping for a 2 seconds for demonstration purposes)
            print("long task \(i) done! \(Date())")
            sem.signal()                             //let the semaphore know this resource is now available
        }
    }
}

Voorbeelduitvoer: (let op de tijdstempels)

starting long running tasks (2 at a time)
long task 0 done! 2017-02-16 07:11:53 +0000
long task 1 done! 2017-02-16 07:11:53 +0000
long task 2 done! 2017-02-16 07:11:55 +0000
long task 3 done! 2017-02-16 07:11:55 +0000
long task 5 done! 2017-02-16 07:11:57 +0000
long task 4 done! 2017-02-16 07:11:57 +0000
long task 6 done! 2017-02-16 07:11:59 +0000
long task 7 done! 2017-02-16 07:11:59 +0000

Raadpleeg de Apple Docs voor meer informatie

Seriële versus gelijktijdige verzendwachtrijen

Swift 3

Seriële wachtrij

func serialQueues () {
    let serialQueue = DispatchQueue(label: "com.example.serial") //default queue type is a serial queue
    let start = Date ()
    for i in 0...3 {                                             //launch a bunch of tasks
        serialQueue.async {                                      //run tasks on a background thread, using our serial queue
            sleep(2)                                             //do some long task eg webservice or database lookup
            let timeTaken = Date().timeIntervalSince(start)
            print("serial long task \(i) done! total time taken: \(timeTaken)")
        }
    }
}

Voorbeelduitgang:

serial long task 0 done! total time taken: 2.07241100072861
serial long task 1 done! total time taken: 4.16347700357437
serial long task 2 done! total time taken: 6.23209798336029
serial long task 3 done! total time taken: 8.30682599544525

Gelijktijdige wachtrij

func concurrentQueues () {
    let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent) //explicitly specify the queue to be a concurrent queue
    let start = Date ()
    for i in 0...3 {            //launch a bunch of tasks
        concurrentQueue.async { //run tasks on a background thread, using our concurrent queue
            sleep(2)            //do some long task eg webservice or database lookup
            let timeTaken = Date().timeIntervalSince(start)
            print("concurrent long task \(i) done! total time taken: \(timeTaken)")
        }
    }
}

Voorbeelduitgang:

concurrent long task 3 done! total time taken: 2.07092100381851
concurrent long task 0 done! total time taken: 2.07087397575378
concurrent long task 2 done! total time taken: 2.07086700201035
concurrent long task 1 done! total time taken: 2.07089096307755

Discussie

Zoals we in de bovenstaande voorbeelden kunnen zien, voltooit een seriële wachtrij elke taak in de volgorde waarin ze naar de wachtrij zijn verzonden. Elke taak wacht totdat de vorige taak is voltooid voordat deze wordt uitgevoerd. Wat de gelijktijdige wachtrij betreft, wacht elke taak niet op de anderen in de wachtrij en wordt deze zo snel mogelijk uitgevoerd; het voordeel is dat alle taken in de wachtrij tegelijkertijd op afzonderlijke threads worden uitgevoerd, waardoor een gelijktijdige wachtrij minder tijd kost dan een seriële wachtrij.

Als de volgorde van uitvoering van taken niet belangrijk is, gebruik dan altijd een gelijktijdige wachtrij voor de beste efficiëntie.



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