it-swarm.com.de

iPhone - Hauptthread von Grand Central Dispatch

Ich habe mit Erfolg Grand Central Dispatch in meinen Apps verwendet, aber ich habe mich gefragt, was der wahre Vorteil der Verwendung von so etwas ist:

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

oder auch

dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff

Ich meine, in beiden Fällen wird ein Block ausgelöst, der auf dem Haupt-Thread ausgeführt werden soll, genau dort, wo die App ausgeführt wird, und dies wird nicht dazu beitragen, die Last zu reduzieren. Im ersten Fall haben Sie keine Kontrolle darüber, wann der Block ausgeführt wird. Ich habe Fälle von Blöcken gesehen, die eine halbe Sekunde nach dem Abfeuern ausgeführt wurden. Der zweite Fall ist ähnlich

[self doStuff];

recht?

Ich frage mich, was denkt ihr?.

145
SpaceDog

Das Senden eines Blocks an die Hauptwarteschlange erfolgt normalerweise von einer Hintergrundwarteschlange aus, um anzuzeigen, dass einige Hintergrundverarbeitungen abgeschlossen sind, z.

- (void)doCalculation
{
    //you can use any string instead "com.mycompany.myqueue"
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_async(backgroundQueue, ^{
        int result = <some really long calculation that takes seconds to complete>;

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateMyUIWithResult:result];
        });    
    });
}

In diesem Fall führen wir eine lange Berechnung in einer Hintergrundwarteschlange durch und müssen unsere Benutzeroberfläche aktualisieren, wenn die Berechnung abgeschlossen ist. Das Aktualisieren der Benutzeroberfläche muss normalerweise von der Hauptwarteschlange aus erfolgen, damit wir mit einem zweiten verschachtelten dispatch_async-Befehl an die Hauptwarteschlange zurücksenden.

Es gibt wahrscheinlich noch andere Beispiele, bei denen Sie möglicherweise eine Rückübertragung an die Hauptwarteschlange durchführen möchten, dies geschieht jedoch im Allgemeinen auf diese Weise, d. H. Innerhalb eines Blocks verschachtelt, der an eine Hintergrundwarteschlange gesendet wird.

  • hintergrundverarbeitung beendet -> Benutzeroberfläche aktualisieren
  • datenblock, der in der Hintergrundwarteschlange verarbeitet wird -> Hauptwarteschlange signalisieren, um den nächsten Block zu starten
  • eingehende Netzwerkdaten in der Hintergrundwarteschlange -> Signalisieren Sie der Hauptwarteschlange, dass die Nachricht angekommen ist
  • etc etc

Warum möchten Sie möglicherweise an die Hauptwarteschlange senden? von die Hauptwarteschlange ... Nun, im Allgemeinen würden Sie dies nicht tun, obwohl es vorstellbar ist, dass Sie einige Arbeiten planen, die beim nächsten Mal in der Warteschlange ausgeführt werden sollen run loop.

293

Das Verteilen von Blöcken vom Hauptthread an die Hauptwarteschlange kann nützlich sein. Dadurch kann die Hauptwarteschlange andere in die Warteschlange eingereihte Blöcke verarbeiten, sodass Sie nicht einfach die Ausführung aller anderen Blöcke blockieren.

Beispielsweise könnten Sie einen Server mit einem einzigen Thread schreiben, der dennoch viele gleichzeitige Verbindungen verarbeitet. Solange kein einzelner Block in der Warteschlange zu lange dauert, reagiert der Server auf neue Anforderungen.

Wenn Ihr Programm nichts anderes tut, als sein ganzes Leben lang auf Ereignisse zu reagieren, kann dies ganz natürlich sein. Sie richten Ihre Ereignishandler so ein, dass sie in der Hauptwarteschlange ausgeführt werden, und rufen dann dispatch_main () auf. Möglicherweise müssen Sie sich überhaupt nicht um die Thread-Sicherheit kümmern.

15
bames53

Hoffentlich verstehe ich Ihre Frage richtig, da Sie sich über die Unterschiede zwischen dispatch_async und dispatch_sync wundern.

dispatch_async

sendet den Block asynchron an eine Warteschlange. Dies bedeutet, dass der Block an die Warteschlange gesendet wird und nicht auf die Rückkehr gewartet wird, bevor die Ausführung des verbleibenden Codes in Ihrer Methode fortgesetzt wird.

dispatch_sync

sendet den Block synchron an eine Warteschlange. Dies verhindert die weitere Ausführung des verbleibenden Codes in der Methode, bis der Block die Ausführung beendet hat.

Ich habe meistens ein dispatch_async in eine Hintergrundwarteschlange, um die Hauptwarteschlange zu verlassen und die zusätzlichen Kerne des Geräts zu nutzen. Dann dispatch_async an den Haupt-Thread, wenn ich die Benutzeroberfläche aktualisieren muss.

Viel Glück

11
timthetoolman

Ein Ort, an dem es nützlich ist, ist für UI-Aktivitäten wie das Festlegen eines Drehfelds vor einer längeren Operation:

- (void) handleDoSomethingButton{

    [mySpinner startAnimating];

    (do something lengthy)
    [mySpinner stopAnimating];
}

wird nicht funktionieren, weil Sie den Haupt-Thread während Ihrer langen Zeit blockieren und UIKit den Spinner nicht starten lassen.

- (void) handleDoSomethingButton{
     [mySpinner startAnimating];

     dispatch_async (dispatch_get_main_queue(), ^{
          (do something lengthy)
          [mySpinner stopAnimating];
    });
}

gibt die Steuerung an die Ausführungsschleife zurück, die die Aktualisierung der Benutzeroberfläche plant, den Spinner startet und dann das nächste Element aus der Versandwarteschlange holt, bei dem es sich um Ihre tatsächliche Verarbeitung handelt. Wenn Ihre Verarbeitung abgeschlossen ist, wird der Animationsstopp aufgerufen, und Sie kehren zur Ausführungsschleife zurück, in der die Benutzeroberfläche dann mit dem Stopp aktualisiert wird.

8
weaselfloss1

Swift 3, 4 & 5

Laufender Code im Hauptthread

DispatchQueue.main.async {
    // Your code here
}
8
Niall Kiddle

Async bedeutet asynchron und sollte die meiste Zeit verwendet werden. Sie sollten die Synchronisierung niemals für den Haupt-Thread aufrufen, da die Benutzeroberfläche so lange gesperrt bleibt, bis die Aufgabe abgeschlossen ist. Hier ist ein besserer Weg, dies in Swift zu tun:

runThisInMainThread { () -> Void in
    // Run your code like this:
    self.doStuff()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

Es ist als Standardfunktion in meinem Repo enthalten, probiere es aus: https://github.com/goktugyil/EZSwiftExtensions

1
Esqarrouth