Save in Core Data from another thread

  • Hello,
    I've a program that receive lots of data from a network connection.
    As data arrives I've used Core Data insertObject in order to put a
    description of data into my managed context and a complete data
    reference in a file handle (core data is basically an index).
    This work pretty well but while when I try to fetch data from another
    persistent store when the first still receive data it works fast if I
    click on a fetched item it takes lots of time, and I can see the
    contents only when the other threads has finished to get data.
    I've tried this solution:

    - (void) storeList:(NSArray *)listOfMessages {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int k;
    NSManagedObjectContext *ctx = [self newIstanceManagedObjectContext];
    for (k=0;k < [listOfMessages count]; k++) {
      [self _storeArticleDataInThisArchive: [listOfMessages
    objectAtIndex:k] inCtx: ctx];
    }
    [listOfMessages removeAllObjects];
    [pool release];
    }

    where newIstanceManagedObjectContext creates a new ctx:

    - (NSManagedObjectContext *) newIstanceManagedObjectContext {
    NSPersistentStoreCoordinator *coordinator = [self
    persistentStoreCoordinator];
        if (coordinator != nil) {
            NSManagedObjectContext *_managedObjectContext =
    [[NSManagedObjectContext alloc] init];
                    [_managedObjectContext
    setRetainsRegisteredObjects:YES];

      [_managedObjectContext setPersistentStoreCoordinator: coordinator];

      return [_managedObjectContext autorelease];
        }
    return nil;
    }

    Unfortunatly it does not works because on saving the results is this:

    repareForSave:: save for NSSQLCore 0xf0b1670 is already in progress
    Error Domain=NSCocoaErrorDomain Code=259 UserInfo=0x169235d0 "The file
    “test” could not be opened because it is not in the right format."

    What's wrong in my code? How can I perform a thread-safe saving/
    inserting?
    Thanks
  • On Oct 29, 2007, at 5:57 PM, malcom wrote:

    > PrepareForSave:: save for NSSQLCore 0xf0b1670 is already in progress
    > Error Domain=NSCocoaErrorDomain Code=259 UserInfo=0x169235d0 "The
    > file “test” could not be opened because it is not in the right
    > format."
    >
    > What's wrong in my code?

    You haven't given us enough information to really say.  You need to
    show us what show us the code that actually performs the save, and
    also the code that passes the messages to save.

    Also, some naming convention issues with the code you have shown:

    (1) Your -newIstanceManagedObjectContext method misspells "instance"
    and should return a non-autoreleased object (since it starts with
    "new").

    (2) -storeList: is very generic, and mis-named to boot.  An NSArray is
    not a list; you would be better off calling it something like -
    saveMessages:.

    There's one other issue that may be at the heart of the whole matter,
    and may mean that what you're attempting to do is simply unsupported:

    Objects inserted in one managed object context are not made available
    to other managed object contexts by Core Data until they are saved,
    even if all of the managed object contexts involved share a persistent
    store coordinator.  In other words, only objects that are actually in
    an underlying persistent store are available to all managed object
    contexts via that persistent store.

      -- Chris
  • On Oct 30, 2007, at 4:33 AM, Chris Hanson wrote:

    > (1) Your -newIstanceManagedObjectContext method misspells "instance"
    > and should return a non-autoreleased object (since it starts with
    > "new").
    >
    > (2) -storeList: is very generic, and mis-named to boot.  An NSArray
    > is not a list; you would be better off calling it something like -
    > saveMessages:.

    Ok I'll fix it.

    > There's one other issue that may be at the heart of the whole
    > matter, and may mean that what you're attempting to do is simply
    > unsupported:
    >
    > Objects inserted in one managed object context are not made
    > available to other managed object contexts by Core Data until they
    > are saved, even if all of the managed object contexts involved share
    > a persistent store coordinator.  In other words, only objects that
    > are actually in an underlying persistent store are available to all
    > managed object contexts via that persistent store.

    The part of the code involved in save action inside my method is
    pretty simple:

    - (ANTArtNode *) _storeArticleDataInThisArchive:(NSString *) _rawData
    onlyHeader:(BOOL) _onlyHeader ctx:(NSManagedObjectContext *) ctx {
    // ... additional code not related with core data
    ANTArtNode *art = [[ANTArtNode alloc] initWithEntity:
    [NSEntityDescription
      entityForName: @"ARTICLE" inManagedObjectContext: ctx]
      insertIntoManagedObjectContext: nil];

    [ctx insertObject: art];
    // ... additional code not related with core data
    return art;
    }

    while the part of the code involved in calling saveList is:

    // ... blablabla
    if ([listOfTempArticles count] == MIN_CHUNK_TO_SAVE) {
    [[[group databaseArchive] persistentStoreArchive] saveList:
    listOfTempArticles];
    //[NSThread detachNewThreadSelector: @selector(saveList:) toTarget:
    [[group databaseArchive] persistentStoreArchive]
    withObject:listOfTempArticles];
    }
    // ... blablabla

    It saves a list each MIN_CHUNK_TO_SAVE new chunck.
    Now what I would to do is to perform save/insertObject operation on
    these object in a background thread. It's not important that user can
    see these new messages instantly but he should have the opportunity to
    browse other persistent store (actually while core data try to insert
    these object the interface become pretty unresponsive).
    I've tried with detachNewThreadSelector + other new managed object as
    you can see from commented code but it's the same thing (really, no
    the same, it is worse than the before).
    However I could perform a save each x seconds with a timer or perform
    a save operation each x chunck, but probability there is an error in
    my approach with core data and multithreading programming that I don't
    know how to solve.
    Thanks.

    malcom
previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today