Ich habe einige Berechnungen im Hintergrund-Thread, danach muss ich die Transformation einiger calayer aktualisieren, ich versuche
zu verwenden %Vor%und
%Vor%Ich dachte nur, sie sind gleich, aber ich fand die calayer funktionierte sehr glatt (vielleicht?), wenn Sie disass_async verwenden. Was ist der Unterschied zwischen diesen beiden Funktionen?
Der Hauptunterschied besteht hier darin, dass CFRunLoopPerformBlock
Ihnen erlaubt, bestimmte Lauf-Loop-Modi anzugeben, in denen der Block ausgeführt wird, während dispatch_async(dispatch_get_main_queue(),...)
nur in allgemeinen Modi ausgeführt wird. Vielleicht hängt es mehr von dem Leistungsproblem ab, das Sie sehen, CFRunLoopPerformBlock
macht nicht den Hauptthread aktiv. Aus der Dokumentation für CFRunLoopPerformBlock
:
Diese Methode reiht den Block nur in die Warteschlange ein und wacht nicht automatisch auf die angegebene Laufschleife. Daher erfolgt die Ausführung des Blocks die Beim nächsten Mal wird die Laufschleife aktiviert, um eine andere Eingabequelle zu verarbeiten. Wenn du Willst du die Arbeit sofort erledigen, musst du das explizit aufwecken Thread mit der Funktion CFRunLoopWakeUp.
In der Praxis bedeutet dies normalerweise, dass Ihr Block erst ausgeführt wird, wenn die Laufschleife aufwacht (dh Benutzerereignis tritt auf, Timer wird ausgelöst, Schleifenquellen werden ausgelöst, Mach-Nachricht wird empfangen usw.). GCD ist nicht per Entwurf, eine Run-Loop-basierte API; Die Beziehung zwischen der Hauptwarteschlange und der Hauptthreadlaufschleife ist effektiv ein Implementierungsdetail. Ich würde erwarten, dass diese Implementierung die Ausführungsschleife selbst aufweckt, wenn dies für die Hauptwarteschlange erforderlich wäre.
Wenn keine gegenteiligen Informationen vorliegen, vermute ich, dass dies die Ursache für den Leistungsunterschied ist. Ich würde erwarten, dass die Leistung ähnlich ist, wenn Sie einen Aufruf von CFRunLoopWakeUp
direkt nach Ihrem Aufruf an CFRunLoopPerformBlock
hinzugefügt haben.
Die Hauptwarteschlange von GCD ist eine serielle Warteschlange. Es kann also nur eine Aufgabe gleichzeitig ausführen. Selbst wenn diese Task eine innere Ausführungsschleife ausführt, z. B. einen modalen Dialog ausführt, können andere Aufgaben, die an die Hauptwarteschlange übergeben werden, erst ausgeführt werden, wenn dies abgeschlossen ist.
Aufgaben, die mit CFRunLoopPerformBlock()
übergeben wurden, können ausgeführt werden, wenn die Laufschleife in einem der Zielmodi ausgeführt wird. Dies gilt auch, wenn die Laufschleife von einer Task ausgeführt wird, die mit CFRunLoopPerformBlock()
gesendet wurde.
Betrachten Sie die folgenden Beispiele:
%Vor%erzeugt eine Ausgabe wie:
%Vor%Währenddessen:
%Vor%erzeugt:
%Vor%Ich benutze sie manchmal zusammen:
%Vor%Ich benutze dies, um einen Block an den Haupt-Thread zu senden, der ausgeführt wird, ohne "Störungen" zu verursachen, wenn ein UIScrollview scrollt.
Ich habe auch kürzlich verwendet:
%Vor%anstelle von:
%Vor%, um die Ausführung des Codes für den nächsten Durchlauf durch den Runloop zu verzögern. Auf diese Weise muss ich keine spezielle Methode erstellen, die den Code enthält, den ich ausführen möchte, und muss nicht alle Parameter zur Ausführung in ein einziges (id) myObject umwandeln.
Tags und Links multithreading ios grand-central-dispatch