2011-11-18 42 views
2

问题:我如何让核心日期合并在两个不同线程中对同一NSManagedObject所做的更改?线程更改不同的属性,并且这些属性的任意组合都是有效的。核心数据和竞赛条件

有一个应用程序(至少)有两个线程,UI线程后台线程。 所谓的DocumentNSManagedObject的子类。 A Document有三个属性,attrA,attrBattrC

后台线程读取attrA和写入attrB,如:

doc.attbB = md5(doc.attrA); 

(实际上,它是更复杂,更费时,但你的想法)。

UI线程显示所有attrAattrBattrC给用户,并允许用户更改attrAattrC。 (有些同时attrB值无效。)

我强调的是,只有UI线程写入attrA,只有后台线程写入attrB

现在,用户在attrB计算完成之前更改attrC后台线程尝试保存attrB并出现错误。 我现在所做的是:

if(!saved) { 
    // I did try to check that it's *that* kind of error, 
    // but that's iOS5-specific, while I need 4.3 
    // (comments on error type checking in 4.3 are welcome). 
    // Anyway, finally it was this: 
    id tmp = doc.attrB; 
    [[doc managedObjectContext] refreshObject:doc mergeChanges:NO]; 
    doc.attrB = tmp; 
    BOOL saved = [context save:&error]; 
    // NSLog if it still failed 
} 

在一般情况下,这是不行的。

起初,会发生什么,如果更多的变化将这些线之间进行:

[[doc managedObjectContext] refreshObject:doc mergeChanges:NO]; 
    doc.attrB = tmp; 
    // more changes happen here!!! 
    BOOL saved = [context save:&error]; 

是的,我能如果一段时间,但它不是一般情况下的解决方案取代。如果这些变化反复发生,这可能是一个无限循环。

第二,UI线程也可能试图保存一些东西。在我看到的旨在合并更改代码的类之一,

#pragma mark Changes Propagation 

- (void)__contextDidSave:(NSNotification*)notification 
{ 
    [parent performSelectorOnMainThread:@selector(__mergeChanges:) withObject:notification waitUntilDone:NO]; 
} 

- (void)__mergeChanges:(NSNotification*)notification 
{ 
    [objectContext mergeChangesFromContextDidSaveNotification:notification]; 
    if (parent) { 
     [parent __mergeChanges:notification]; 
    } 
} 

据我了解,__mergeChanges将正确的线程上运行,但不会立即;这是可能的UI线程将试图挽救改变attrB后台线程后的变化attrAattrC__mergeChanges之前运行。

这是一个典型的竞赛条件。

问题:我如何正确使核心日期合并在两个不同线程中对同一NSManagedObject所做的更改? (线程更改不同的属性,并且这些属性的任意组合都是有效的,但核心数据不知道这一点。)

回答

0

我不是核心数据的专家,但我猜你可以使用同步指令:

// UI Thread 
@synchronized(AN_INSTANCE_OF_ANY_OBJECT) { 
    // your first thread's code goes here 
} 

// Background Thread 
@synchronized(THE_SAME_INSTANCE_OF_THE_OBJECT) { 
    // your second thread's code goes here 
} 

这应该停止所有线程的执行,如果有其他正在执行的范围,注意到该实例应该是相同的,因此,如果您不能访问该实例可以使用一个公共的静态实例,它通常可以帮助我做这个伎俩。

+0

两个不同的线程有两个不同的'NSManagedObject's。也就是说,我无法将它们用于锁定。也就是说,我需要一个全局锁。第二,范围是什么?除非我错过了一些东西,它看起来像是将一个保存包装到'@ synchronized'中不会有任何好处。而且,我如何将通知包装到'@ synchronized'中?应该有一整章的同步,但由于某种原因我找不到它。我希望这不是因为它不在那里。 – 18446744073709551615