Sök…


Introduktion

Relaterat ämne: Grand Central Dispatch

Syntax

  • dispatch_async - Kör ett block med kod i en separat kö och stoppar inte den aktuella kön. Om kön är på en annan tråd än den som dispatch_async anropades, kommer koden i blocket att köras medan koden efter att dispatch_async också körs
  • dispatch_sync - Kör ett block av kod i en separat kö, och hindrar den aktuella kön. Om kön är på en annan tråd än den som dispatch_async anropades, kommer koden i blocket att köras, och exekveringen på tråden där metoden anropades kommer att återupptas först när den är klar

parametrar

Kön som koden i avsändningsblocket kommer att köras i. En är som (men inte exakt samma som) en tråd; kod i olika köer kan köras parallellt. Använd dispatch_get_main_queue att få kön för huvudtråden För att skapa en ny kö, som i sin tur skapar en ny tråd, använd dispatch_queue_create("QUEUE_NAME", DISPATCH_QUEUE_CONCURRENT) . Den första parametern är köets namn, som visas i felsökaren om du pausar medan blocket fortfarande körs. Den andra parametern spelar ingen roll om du inte vill använda samma kö för flera dispatch_async eller dispatch_sync samtal. Den beskriver vad som händer när ett annat block sätts i samma kö; DISPATCH_QUEUE_CONCURRENT kommer att göra att båda blocken körs samtidigt, medan DISPATCH_QUEUE_SERIAL får det andra blocket att vänta på att det första blocket är slut
blockera Kod i detta block kommer att köras i kön queue ; sätta kod du vill köra i den separata kön här. Ett användbart tips: Om du skriver detta i Xcode och blockargumentet har den blå konturen runt det, dubbelklickar du på argumentet och Xcode kommer automatiskt att göra ett tomt block (detta gäller alla blockargument i någon funktion eller metod)

Anmärkningar

Varje gång du gör något på en separat tråd, vilket händer när du använder köer, är det viktigt att bibehålla gängesäkerheten. Vissa metoder, särskilt sådana för UIView , kanske inte fungerar och / eller kraschar på andra trådar än huvudtråd. Se också till att inte ändra någonting (variabler, egenskaper etc.) som också används på huvudtråden, såvida du inte redovisar den här ändringen

Körningskod samtidigt - Körkod medan du kör annan kod

Säg att du vill utföra i handling (i detta fall logga "Foo"), medan du gör något annat (loggar "Bar"). Normalt, om du inte använder samtidighet, kommer en av dessa åtgärder att genomföras fullt ut, och den andra körningen kommer att köras först när den är helt klar. Men med samtidighet kan du låta båda åtgärderna köras samtidigt:

dispatch_async(dispatch_queue_create("Foo", DISPATCH_QUEUE_CONCURRENT), ^{
    for (int i = 0; i < 100; i++) {
        NSLog(@"Foo");
        usleep(100000);
    }
});

for (int i = 0; i < 100; i++) {
    NSLog(@"Bar");
    usleep(50000);
}

Detta kommer att logga "Foo" 100 gånger, pausa i 100 ms varje gång det loggar, men det kommer att göra allt detta på en separat tråd. Medan Foo loggas, kommer "Bar" också att loggas i intervaller på 50 ms, samtidigt. Du bör helst se en utgång med "Foo" och "Bars" blandade

Utför på huvudtråden

När du utför uppgifter asynkront blir det vanligtvis ett behov av att se till att en kodkod körs på huvudtråden. Till exempel kanske du vill träffa ett REST API asynkront, men lägg resultatet i en UIL-etikett på skärmen. Innan du uppdaterar UIL-etiketten måste du se till att din kod körs i huvudtråden:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //Perform expensive tasks
    //...

    //Now before updating the UI, ensure we are back on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        label.text = //....
    });
}

Varje gång du uppdaterar vyer på skärmen ska du alltid se till att du gör det på huvudtråden, annars kan odefinierat beteende uppstå.

Sändningsgrupp - väntar på att andra trådar är slutförda.

dispatch_group_t preapreWaitingGroup = dispatch_group_create();

dispatch_group_enter(preapreWaitingGroup);
[self doAsynchronousTaskWithComplete:^(id someResults, NSError *error) { 
    // Notify that this task has been completed.
    dispatch_group_leave(preapreWaitingGroup);  
}]

dispatch_group_enter(preapreWaitingGroup);
[self doOtherAsynchronousTaskWithComplete:^(id someResults, NSError *error) { 
    dispatch_group_leave(preapreWaitingGroup);  
}]

dispatch_group_notify(preapreWaitingGroup, dispatch_get_main_queue(), ^{
    // This block will be executed once all above threads completed and call dispatch_group_leave
    NSLog(@"Prepare completed. I'm readyyyy");
});

Uppdatering 1. Swift 3-version.

let prepareGroup = DispatchGroup()
prepareGroup.enter()
doAsynchronousTaskWithComplete() { (someResults, error) in
    // Notify that this task has been completed.
    prepareGroup.leave()
}

prepareGroup.enter()
doOtherAsynchronousTaskWithComplete() { (someResults, error) in
    // Notify that this task has been completed.
    prepareGroup.leave()
}

prepareGroup.notify(queue: DispatchQueue.main) {
    // This block will be executed once all above threads completed and call dispatch_group_leave
    print("Prepare completed. I'm readyyyy")
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow