[CoreData] Background Insertion (was Save in Core Data from another thread)

  • Looking at this thread
    <http://www.cocoabuilder.com/archive/message/cocoa/2007/6/5/184252>

    I've used this code in order to perform a background insertion:

    This is the method that create a new thread. I've decided to make a
    new thread each x messages received (and this should be a problem):

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

    This is my thread method:
    - (void) storeArticleDataList:(NSMutableArray *) listOfMessages {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [listOfMessages retain];

    // MAKE MY MANAGED OBJECT CONTEXT LINKED TO THE SAME PERSISTENT STORE
    NSManagedObjectContext *context = [self autoreleaseManagedObjectContext];

    // ARCHIVE MY DATA. Inside this method there is a [context
    insertObject: newCreatedObject];
    int k;
    for (k=0;k < [listOfMessages count]; k++)
      [self _storeArticleDataInThisArchive: [listOfMessages
    objectAtIndex:k] onlyHeader: NO ctx: context];
    [listOfMessages removeAllObjects];

    // SAVE THIS CONTEXT, COLLECT THE OBJECTID AND PASS IT TO THE MAIN THREAD
    NSSet* insertedObjects = [context insertedObjects];
    NSError *error = nil;
      if ( [context save:&error] ) {
      NSSet* insertedIDs = [[insertedObjects valueForKey:@"objectID"] retain];
      [self performSelectorOnMainThread:@selector(dataSaved:)
    withObject:insertedIDs waitUntilDone:NO];
    }
    [pool release];
    }

    This is the method called in main thread. It refresh newly inserted object.

    - (void) dataSaved:(NSSet * )list {
          NSEnumerator* enumerator = [list objectEnumerator];
          NSManagedObjectID* objectid;

          while ( (objectid = [enumerator nextObject]) != nil ) {
              NSManagedObject* object = [managedObjectContext
    objectWithID:objectid];
              [managedObjectContext refreshObject:object mergeChanges:NO];
          }
      [list release];
    }

    Now the problem is this. If I try to perform a partial save (for
    example each 100 messages with a total of 500, so 5 threads) when the
    second thread starts the program crash.
    Why? My opinion is this: because at each insertion the program search
    for the parent of newly inserted message if this parent is not
    available (core data is saving it in previous thread) the second
    thread cannot found it. I think that the problem is this. Anyone have
    a solution? Should I perform a single background save in order to
    perform a correct operation? What's the standard way?
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