joels
joels

Reputation: 7721

how to update other contexts with changes from alternate threads

I have a mainContext that is used on the main thread. When the mainContext is created, I add an observer to the NotificationCenter for NSManagedObjectContextDidSaveNotification notifications.

If a new thread gets created and needs an NSManagedObjectContext, I create the context on the new thread and store some info for it. I save changes to the context on the new thread.

My notification handler gets called and merges changes for all contexts on their threads. I have a merge policy for each context in affect and I am merging changes on the appropriate threads.

I still randomly get "optimistic locking failure". Is there something I am missing?

- (void)contextChanged:(NSNotification *)notif
{

    //gets called from the thread(where the context was) that made the changes
    //iterate over all contexts and mergeChanges on their thread
    NSLog(@"NotifContext %@ %p", [notif object], [NSThread currentThread]);

    //always check the main
    if([notif object] != [self mainContext]){
        NSLog(@"merge with main %@", [self mainContext]);
        [[self mainContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notif waitUntilDone:NO];
    }


    //check alternate cotexts and merge changes on their threads
    NSDictionary *altContexts = [self.altContexts copy];
    for(NSString *threadAddress in altContexts){
        NSDictionary *info = [altContexts objectForKey:threadAddress];
        NSManagedObjectContext *context = [info objectForKey:@"context"];
        if(context != NULL && [notif object] != context){
            NSLog(@"merge with %@", context);
            NSThread *thread = [info objectForKey:@"thread"];
            [context performSelector:@selector(mergeChangesFromContextDidSaveNotification:) onThread:thread withObject:notif waitUntilDone:NO];
        }else{
            NSLog(@"not with %@", context);
        }
    }
    [altContexts release];
}

Upvotes: 0

Views: 86

Answers (1)

joels
joels

Reputation: 7721

waitUntilDone:NO //should have been YES

I overlooked this. I meant to wait until it was done. Otherwise, the save happens (on thread 2), the notification gets dispatched, the contextChanged: handler gets triggered, the other contexts are told to merge changes on their thread (say thread 1), and thread 2 continues before the context on thread 1 actually gets to save.

Upvotes: 0

Related Questions