CoreData, Multi Threading, Bindings und das alles zusammen und "gleichseitig"

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • CoreData, Multi Threading, Bindings und das alles zusammen und "gleichseitig"

    Hallo Leute,

    ich habe eine kleine Test-App gebastelt, die oben genanntes können soll.

    In der App kann man eine neue Firma erstellen und dazu x viele Angestellte.


    Die Angestellten werden in ihrem eigenen Thread erstellt und sobald dies geschehen ist, der einen Firma hinzugefügt.

    Da zwischen Theras keine MangedObject weitergereicht werden dürfen, übergebe ich jedem Thread die ObjectID der Firma.

    Um nicht gleichzeitig auf den gleichen ManagedObjectContext zuzugreifen, erstelle ich für jeden Thread einen neuen Context und lasse ihn dann mit - (void)mergeChanges:(NSNotification *)Notifikation mit dem Haupt-Context "verschmelzen".

    Die Angestellten und die Firmen werden in zwei TableViews angezeigt. Das ganze funktioniert über zwei ArrayController und Bindings.


    Allerdings schein irgendwo noch der Harken drin zu sein. Erstelle ich eine neue Firma mit x neuen Angestellten, fehlen immer ca. 70% der Angestellten. Irgendwo gehen diese verloren. Ich kann nur nicht rausfinden an welcher Stelle.


    Vielleicht mag mal jemand in den Quellcode schauen. Habe das Xcode Projekt hier hochgeladen: osxentwicklerforum.de/index.ph…511d10c6a6d7e7dbc9a57f508

    Es ist nicht viel Code und eigentlich recht simpel. Eigentlich...

    Gruß
    Daniel
    “I want to see an elephant hunt down a man for the sole purpose of collecting his teeth, while a chorus of typewriters sings songs that praises the bananas for their wisdom, leadership, and their high levels of potassium.” ― Jarod Kintz, I Want

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Daniel2 ()

  • @ Plany: Habe ich. Das hat mich ja so weit gebracht. Meinst du etwas bestimmtes?
    “I want to see an elephant hunt down a man for the sole purpose of collecting his teeth, while a chorus of typewriters sings songs that praises the bananas for their wisdom, leadership, and their high levels of potassium.” ― Jarod Kintz, I Want
  • Managed objects themselves are not thread safe.
    If you want to work with a managed object across different threads, you must lock its context (see NSLocking).


    du startest sagen wir 100 Threads und alle sollen gleichzeitig schreiben. obwohl nur 1 immer schreiben kann. nach den Motto wer zuerstkommt schreibt zuerst und da wo es gerade gelockt ist, die haben Pech.

    du hast 3 Möglichkeiten: NSOperationQueue, Rekursive Methode, oder du checkst ob es locker (NSLocked) ist, wenn ja sleep und checken.

    wobei 1 und 2 die bessere Wahl ist :)
    俺の世界にようこそ
  • Achso. Ich dachte fälschlicherweise dass mergeChangesFromContextDidSaveNotification das verhindert.

    Ich versuche das ganze mal mit NSOperation und berichte dann. Was genau meinst du mit Rekursive Methode ?
    “I want to see an elephant hunt down a man for the sole purpose of collecting his teeth, while a chorus of typewriters sings songs that praises the bananas for their wisdom, leadership, and their high levels of potassium.” ― Jarod Kintz, I Want
  • du startest ein thread (methode) und diese Methode ruft sich solange selber auf bis nix mehr zum eintragen da ist

    MainThread:
    Methode zum erstellen von 10 eintragen -> ruft threaded method auf (addRow:0 Limit:10)

    subThread (addRow):
    Methode schreibt den ersten row in CD
    ++i < limit ... ruft sich selber auf mit "addRow:i Limit:10"

    sinn ist das die Methode sich so oft selber aufruft bis eine operation nicht mehr erfühlt wird ... solche Funktionen ersparen ein eine menge code :)

    sowas benutz ich meist weil ich diesen OperationQueue nicht vertraue :P
    俺の世界にようこそ
  • Naja, aber würde ich das mit so einer Rekursive Methode machen, hätte ich ja keinen Geschwindigkeitsvorteil. Deshalb benutze ich ja überhaupt Theras.

    Das Erstellen der Arbeitnehmer dauert ja so lange. Also nicht hier, aber in meinem eigentlichen Programm wartet die Methode ca. eine halbe Sekunde auf eine Antwort ausm Netz bis es weiter geht...
    “I want to see an elephant hunt down a man for the sole purpose of collecting his teeth, while a chorus of typewriters sings songs that praises the bananas for their wisdom, leadership, and their high levels of potassium.” ― Jarod Kintz, I Want
  • Daniel2 schrieb:

    Also nicht hier, aber in meinem eigentlichen Programm wartet die Methode ca. eine halbe Sekunde auf eine Antwort ausm Netz bis es weiter geht...

    Warum?
    Ziehst du dir die Daten aus einer existierenden Datenbank im Netz?
    Wenn ja: warum greifst du nicht gleich auf diese zu?
    Da NSManagedObjects nicht threadsafe sind kannst du versuchen was du willst, du wirst neue Daten nur nacheinander hineinbekommen. Selbst wenn du den Kontext lockst, bedeutet das nur, dass in der Zeit kein anderer Thread darauf zugreifen kann bis der eine Thread fertig ist.
    Das Ganze ist also mit Managed Objects so nicht realisierbar. Du solltest dir eventuell was Eigenes basteln.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Okay, ich habe vielleicht etwas zu wenig Informationen zu meinem Programm gegeben:
    Ich ping einen Haufen Geräte an und warte eine halbe Sekunde auf eine Antwort. Kommt vor Ablauf dieser Zeit eine Antwort, wird das entsprechende Gerät (Angestellter) gespeichert und der aktuellen Gruppe (Firma) hinzugefügt.

    Was ich eben möchte ist dass ich nicht eine halbe Sekunde warten muss und dann alles rein Haue, sondern sobald ein Gerät gefunden wurde (vielleicht nach 100 ms) dieses auch hinzufüge. Dann darf das natürlich nicht gleichzeitig passieren, aber es muss eben nicht die ganze Zeit abgewartet werden. :/
    “I want to see an elephant hunt down a man for the sole purpose of collecting his teeth, while a chorus of typewriters sings songs that praises the bananas for their wisdom, leadership, and their high levels of potassium.” ― Jarod Kintz, I Want
  • Kann sehr gut sein, dass das was jetzt kommt falsch ist :)
    Warum nimmst du dir nicht ein Array als eine Art cache, wo du das jedes mal reinschreibst in deinem Hintergrundthread, wenn es ankommt. Dann haust du deine Notifikation raus die wiederum die rekursive Methode von Plany verwendet und das Array abarbeitet, das machst du jedesmal, wenn ein neues Ding reinkommt und schon ist es nicht meh gelockt und du musst nicht warten...oder habe ich irgendwas übersehen??
  • Eine ähnliche Idee hatte ich auch schon, allerdings:
    http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html
    Mutable objects are generally not thread-safe. To use mutable objects in a threaded application, the application must synchronize access to them using locks.

    Also auch da keine Hilfe, wenn mehrere Threads rumhorchen sollen.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • scriptedSheep schrieb:

    Man muss das ja nicht mit NSMutableArray machen ...

    Und wie möchtest du ein NSArray aus unterschiedlichen Threads füttern?
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Also ich würde es auch über ein MutualArray machen (vorrausgesetzt es werden nicht soviele Einträge das es nicht mehr ins RAM Passt, aber dann wären die entsprechende Anzqahl Threads wohl auch nicht machbar) und einfach mit jedem Thread auch einen Eintrag in das Array packen. Diese Einträge haben dann ein Flag "Respond" mit 0 initialisiert und ich gebe dem Thread den Zeiger auf den Eintrag mit. Der thread kann dann dieses Flag ändern in "responded" oder "not responeded". Das können dann auch beliebig viele Threads auf einmal.

    Weiterhin kann dann der mainthread dieses Flag abfragen und bei allen Einträgen die schon ein gesetztes Flag haben, diesen Eintrag im CoreData speichern.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Also das ist schon ein schwieriges Thema CoreData und Theras. Ich habe gestern noch paar Sachen ausprobiert. Man findet im Netz schon ein paar Sachen, wie man so etwas machen kann, z.B. hier: duckrowing.com/2010/03/11/usin…-data-on-multiple-threads
    Allerdings geht es dann dabei meistens um nur ein MAnaged Object ohne Beziehungen und so weiter.

    Ich denke irgendeine gute Lösung gibt es.

    Ich mache es jetzt folgendermaßen: Ich erstelle eine x Anfragen alle in ihrem eigenen Thread. Sobald etwas gefunden worden ist füge ich das ganze mit [self performSelectorOnMainThread:@selector(meineMethode:) withObject:Antwort waitUntilDone:YES]; CoreData hinzu und gut ist. So habe ich das Zeitintensive Warten auf eine Antwort im Hintergrund und nur den CoreData Kram im Main Thread. Vielleicht könnte man den CoreData Teil noch in einen eigenen Thread packen. So funktioniert das jetzt erst mal ganz gut.
    “I want to see an elephant hunt down a man for the sole purpose of collecting his teeth, while a chorus of typewriters sings songs that praises the bananas for their wisdom, leadership, and their high levels of potassium.” ― Jarod Kintz, I Want