2013-08-29 8 views
6

Viele Menschen haben eine Frage mit einem ähnlichen Titel gefragt, aber ganz anderen Zweck:dispatch_get_current_queue() veraltet, gibt es eine Alternative für sichere CoreData?

Coredata erfordert, dass Sie den Überblick über Ihre aktuelle Warteschlange zu halten, Ihren aktuellen Thread, und Ihre aktuelle NSOperationQueue (wenn Sie eine NSOperation sind) , wenn Sie zulassen, dass Methodenaufrufe von anderen Klassen kommen (was standardmäßig jede Klasse zulässt). Es gibt keine "maybes" darüber: Es ist eine harte Anforderung.

ist das in Ordnung, und es ist in der Regel leicht zu gewährleisten:

NSAssert([NSThread currentThread].isMainThread || myPrivateQueue == dispatch_get_current_queue(), @"You tried to call this method from an external thread, or a queue other than my internal private queue. That's not legal, and will cause data corruption"); 

... außer, dass Apple gegangen und veraltete dispatch_get_current_queue() hat, anscheinend „, weil die Menschen mißbrauchten es um Funktionalität in GCD fehlt zu erhalten/Bits von GCD haben sie nicht verstanden ".

NB: meine Nutzung von dispatch_get_current_queue() oben erscheint korrekt und nicht missbräuchlich zu sein, die Beurteilung durch Apples Header-Kommentar: Der springende Punkt ist, dass ich überprüfe, dass die Warteschlange der privaten I erstellt (die Ansprüche von Apple ist eine akzeptable Nutzung).

Abgesehen von der Weisheit, etwas zu verwerfen, einfach aufgrund von Fehlern in der Implementierung :(... hat jemand eine Abhilfe gefunden, die von Apple entfernt wurde. Speziell: mit CoreData müssen Sie die Warteschlange verfolgen - gibt es eine andere

(Das ist wichtig, weil: Wenn Sie mit CoreData erlauben, dass etwas versehentlich eine solche Methode aufruft, werden Sie keinen "Absturz" bekommen, Sie werden "Daten korrumpieren" bekommen, die bei erscheinen werden . Irgendwann in der Zukunft, wenn es zu spät ist, es zu beheben ")

+0

Ich habe 'dispatch_queue_set_specific()' und 'dispatch_get_specific()' verwendet, für die Anwendung, die ich hier gefragt habe: http://stackoverflow.com/questions/12806506/how-can-i-verify-that- Ich bin am Laufen-auf-gegeben-gcd-Queue-ohne-Verwendung-dispatch-g und es hat gut funktioniert, um bestimmte Warteschlangen zu identifizieren. Der Kommentar von Jody zu der Antwort erwähnt die Verwendung von etwas ähnlichem in Core Data. –

+0

@BradLarson dispatch_get_specific() ist sehr interessant, danke. Ich bin mir nicht sicher, was passiert, wenn du es nennst, wenn du nicht in einem Block bist (in korrekter Ausführung, würdest du sein), aber ich würde gerne wissen, was passiert, wenn es schief geht, denn das ist das Setup, das ich versuche zu fangen/behaupten/loggen gegen) – Adam

+0

Ich weiß nicht, dass das in einem Block von Bedeutung ist. Alles, was es testet, ist ein Schlüssel, der der bestimmten Warteschlange zugewiesen ist, auf der dieser Code ausgeführt wird. Wie ich dort zeige, verwende ich dies für eine Funktion, die die synchrone Ausführung von Code in einer bestimmten Warteschlange garantiert, indem entweder ein Block synchron an die Warteschlange gesendet wird oder indem der Code direkt ausgeführt wird, wenn er bereits in dieser Warteschlange ist. –

Antwort

4

performBlock immer es in der richtigen Thread ausgeführt verwenden sie einfach:

[yourManagedObjectContext performBlock:^{ 
//do your stuff here 
}]; 

Sie benötigen keinen aktuellen Track-Kontext mehr, da Ihr MOC weiß, welcher Thread dieses MOC an erster Stelle abfeuert. Wenn Sie performBlock oder performBlockAndWait verwenden, sind Sie sicher.

+0

Gute Idee, aber es scheint Probleme mit Thread-Locking und Leistung in komplexen Situationen zu haben - durch "Probleme" meine ich "vielleicht CoreData-Probleme, wahrscheinlich auch Bugs in unserer Codebasis, möglicherweise beides zusammen". Einer meiner ersten Schritte war, großzügig zu argumentieren, um herauszufinden, warum gelegentlich "CoreData für einige Sekunden auf einem Mutex hängt, der unbestritten erscheint". – Adam

+0

... also versuche ich, unser Vertrauen auf "immer performBlock für alles" zu entfernen und herauszufinden, was tatsächlich passiert/nicht passiert – Adam

+0

"Immer' performBlock: 'für alles" ist so ziemlich die empfohlene Art, Dinge zu tun AFAICT. 'dispatch_get_current_queue()' ist aufgrund der Funktionsweise von libdispatch weitgehend nutzlos - es gibt eine kleine Anzahl von "globalen" Warteschlangen und andere Warteschlangen zielen schließlich auf diese Warteschlangen. Dadurch wird dieser Aufruf unbrauchbar, weil er die aktuelle Warteschlange ist. Der eine, in den er eingereiht wurde, oder die globale Queue, auf der er ausgeführt wird.Der Enqueuer ist der Schiedsrichter, in welcher Warteschlange Sie sich befinden.In diesem Fall ist 'performBlock:' der Enqueuer, und das ist die einzige Art zu wissen, wer Sie sind in dieser Warteschlange. – ipmcc

0

In meinem speziellen Fall, ich ersetzt alle performBlock Anrufe von:

  1. alle Coredata Aktionen zu einer einzigen Klasse
  2. die Schaffung eines privaten dispatch_queue
  3. Verschmelzung all meine interne Anrufe zu einem einzigen beweglichen rufen
  4. die einzelnen Anruf hüllt sich in einem dispatch_async ((private interne Warteschlange))
    1. ... und das erste, was es im inneren des dispatc tut h ist "if (self.privateMOC == nil)" ...und schafft die lokale MOC, die gewährleisten, dass die MOC immer nur zugegriffen wird und creatd auf, dass eine Warteschlange

Zwei Dinge geschehen:

  1. der Mutex/lock hängt haben alle verschwunden (obwohl dies sein Zufall konnte - ich werde berichten später zurück, wenn es die Schlösser sind noch stellt sich heraus, blockiert zu werden)
  2. Leistung deutlich besser erscheint als bei performBlock: verwendet wird überall
    1. HINWEIS: Wir hatten viele performBlock-Aufrufe und machten dies häufig (sensible Daten, die die CoreData MOC-Inhalte mit einer moderat hohen Frequenz ändern müssen). Ich weiß nicht, ob es

... so, einen spürbaren Unterschied in einer normalen Anwendung wäre jetzt, für meine Zwecke: dies eine gute Lösung erwiesen hat. Ich glaube nicht, dass es die "richtige" allgemeine Antwort auf die Frage ist, aber ... ich empfehle es jedem, der "performBlock" weniger als Allheilmittel findet als es scheint.

Verwandte Themen