- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有两个 NSManagedObjectContext
,名为 importContext
和 childContext
。 childContext
是 importContext
的 child ,它们都是 NSPrivateQueueConcurrencyType
。
为了让事情远离主线程,我在 importContext
的队列上做了很多工作。这项工作涉及大量的提取和保存,因此将整个事情包装在 importContext
的 performBlockAndWait:
中很方便(它确实需要通过同步操作,因为我在 performBlockAndWait
之后的代码取决于它的结果)。
在这项工作的某个时候,我可能需要从 JSON 结果创建新的托管对象。这些 JSON 值可能无效并且无法通过我的验证,因此在我创建对象之后,如果它们不好,我需要能够抛弃它们。这就是 childContext
的用武之地。我将我的新对象插入其中,如果它的 JSON 属性最终没有意义,我会放弃 childContext
。
当我需要保存 childContext
时,问题就来了。我希望它有自己的专用队列,与其父队列分开。但是,这只会在 iOS 7(而不是 iOS 8)上导致死锁。当我在 iOS 8 模拟器和设备上运行相同的代码时,childContext
会在单独的线程上创建自己的队列并正确保存。
当我运行 iOS 7 时,childContext
试图在父级队列中执行 save:
,但父级正在等待其子级,这会导致僵局。在 iOS 8 中,这不会发生。有谁知道为什么吗?
这是简化的代码:
-(NSManagedObjectContext *)importContext
{
NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.persistentStoreCoordinator = [self storeCoordinator];
return moc;
}
-(void)updateItems:(NSArray*)ItemDescriptions
{
[self.importContext performBlockAndWait:^{
//get info and update
...
...
if(needToCreateNewItem){
NSManagedObjectContext* childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
childContext.parentContext = self.importedContext;
//Insert and create new item
...
[childContext performBlockAndWait:^{
id newObject = [NSEntityDescription insertNewObjectForEntityForName:[self entityName]
inManagedObjectContext:childContext];
}];
...
// Do something with this object
if([newObject isReadyToSave])
__block NSError* e = nil;
__block BOOL saveSucceeded = NO;
[childContext performBlockAndWait:^{
saveSucceeded = [childContext save:&e]; // DEADLOCK ON iOS 7!!!!
}];
}
....
}
}];
}
一个简单的解决方法是将工作保留在单独的调度队列中(而不是 importContext
的队列),但我问这个问题的原因是因为我想了解发生这种情况的根本原因。我认为 child 的保存应该只发生在自己的队列中。
更新 1
回复。马库斯的问题:
updateItems:
从操作队列中的 NSInvocationOperation
调用,因此它不在主队列中。
在 iOS 7 上,我可以随时暂停应用程序并查看堆栈,托管对象上下文的队列将死锁:
(lldb) bt
* thread #7: tid = 0xed07, 0x38546aa8 libsystem_kernel.dylib`semaphore_wait_trap + 8, queue = 'NSManagedObjectContext Queue'
frame #0: 0x38546aa8 libsystem_kernel.dylib`semaphore_wait_trap + 8
frame #1: 0x385bbbac libsystem_platform.dylib`_os_semaphore_wait + 12
frame #2: 0x3848461a libdispatch.dylib`_dispatch_barrier_sync_f_slow + 138
frame #3: 0x2d4f3df2 CoreData`_perform + 102
frame #4: 0x2d4fe1ac CoreData`-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] + 240
frame #5: 0x2d492f42 CoreData`-[NSManagedObjectContext save:] + 826
* frame #6: 0x000c1c96 DBDevApp`__69+[DBManagedObject createWithAttributes:inManagedObjectContext:error:]_block_invoke77(.block_descriptor=<unavailable>) + 118 at DBManagedObject.m:117
frame #7: 0x2d4f6934 CoreData`developerSubmittedBlockToNSManagedObjectContextPerform + 88
frame #8: 0x3847e81e libdispatch.dylib`_dispatch_client_callout + 22
frame #9: 0x384847ca libdispatch.dylib`_dispatch_barrier_sync_f_invoke + 26
frame #10: 0x2d4f6a72 CoreData`-[NSManagedObjectContext performBlockAndWait:] + 106
frame #11: 0x000c1916 DBDevApp`+[DBManagedObject createWithAttributes:inManagedObjectContext:error:](self=0x005c1790, _cmd=0x0054a033, attributes=0x188e context=0x17500800, error=0x02e68ae8) + 658 at DBManagedObject.m:116
frame #12: 0x000fe138 DBDevApp`-[DBAPIController createOrUpdateItems:withIDs:IDKeys:ofClass:amongExistingItems:withFindByIDPredicate:](self=0x17775de0, _cmd=0x0054de newItemDescriptions=0x188eada0, itemIDs=0x18849580, idKey=0x0058e290, class=0x005c1790, existingItems=0x1756b560, findByID=0x18849c80) + 2472 at DBAPIController.m:972
frame #13: 0x00100ca0 DBDevApp`__39-[DBAPIController updatePatientGroups:]_block_invoke(.block_descriptor=0x02e68ce0) + 476 at DBAPIController.m:1198
frame #14: 0x2d4f6934 CoreData`developerSubmittedBlockToNSManagedObjectContextPerform
frame #15: 0x3847e81e libdispatch.dylib`_dispatch_client_callout + 22
frame #16: 0x384847ca libdispatch.dylib`_dispatch_barrier_sync_f_invoke + 26
frame #17: 0x2d4f6a72 CoreData`-[NSManagedObjectContext performBlockAndWait:] + 106
frame #18: 0x00100a96 DBDevApp`-[DBAPIController updatePatientGroups:](self=0x17775de0, _cmd=0x0054dfcd, groupsArray=0x188eada0) + 214 at DBAPIController.m:1191
frame #19: 0x2d721584 CoreFoundation`__invoking___ + 68
frame #20: 0x2d66c0da CoreFoundation`-[NSInvocation invoke] + 282
frame #21: 0x2e0f3d2c Foundation`-[NSInvocationOperation main] + 112
frame #22: 0x2e0515aa Foundation`-[__NSOperationInternal _start:] + 770
frame #23: 0x2e0f576c Foundation`__NSOQSchedule_f + 60
frame #24: 0x38484f10 libdispatch.dylib`_dispatch_queue_drain$VARIANT$mp + 488
frame #25: 0x38484c96 libdispatch.dylib`_dispatch_queue_invoke$VARIANT$mp + 42
frame #26: 0x38485a44 libdispatch.dylib`_dispatch_root_queue_drain + 76
frame #27: 0x38485d28 libdispatch.dylib`_dispatch_worker_thread2 + 56
frame #28: 0x385c0bd2 libsystem_pthread.dylib`_pthread_wqthread + 298
我上面显示的代码是一个简化版本。我创建新子上下文的部分位于名为 DBManagedObject
的类中。这是整个堆栈的屏幕截图:
更新 2 - 解释 DBManagedObject
DBManagedObject
是我所有核心数据类的基类。它基本上处理与 JSON 解析字典之间的转换。它有 3 个主要方法:+createWithAttributes:inManagedObjectContext:error:
、-updateWithAttributes:error:
和 attributes
。
+createWithAttributes:inManagedObjectContext:error:
:创建提供的托管对象上下文的子上下文,在子上下文中插入一个新对象并调用 updateWithAttributes:error:
在那个对象上。如果更新成功(即我们要在此对象上设置的所有值都有意义),它会保存子上下文,在作为参数传入的 MOC 中获取对新对象的引用,并返回该引用:
NSManagedObjectContext* childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
childContext.parentContext = context;
__block id newObject;
[childContext performBlockAndWait:^{
newObject = [NSEntityDescription insertNewObjectForEntityForName:[self entityName] inManagedObjectContext:childContext];
}];
if ([newObject updateWithAttributes:attributes error:error])
{
NSError* e = nil;
if ([childContext save:&e])
{
id parentContextObject = [context objectWithID:[(NSManagedObject*)newObject objectID]];
return parentContextObject;
}
else
{
if (error != NULL) {
*error = e;
}
return nil;
}
}
else
return nil;
updateWithAttributes:error:
:将 JSON 键之间的键转换为我在数据模型中用作实体属性的键。 (即“first_name”变为“firstName”)。如果需要,它还会格式化 JSON 值(日期字符串变为 NSDate
)。它还设置关系。
最佳答案
通过查看您的代码,我发现您有 2 个 [childContext performBlockAndWait:^{ 是嵌套的。删除其中一个应该可以解决您在 ios7 中的问题。该代码已在该线程中运行,您无需再次执行。
始终检查您是否有相同上下文的任何嵌套 performBlocks。这导致我的应用程序在 ios7 之前死锁并在 ios8 中工作
检查方法是当您看到死锁时,在调试器中按下暂停键,查看是什么阻止了所有线程正在运行。查看该特定代码并检查嵌套 block 。
关于ios - performBlockAndWait 在 iOS 7 上具有私有(private)队列死锁父级的子上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26070111/
我有这个 html 代码: HELLO WORLD! X V HELLO WORLD! X V 我想按 X(类关闭)将父 div 的高度更改为 20px 并显示 V(类打开),但在每个 d
在会计应用程序的许多不同实现中,有两种主要的数据库设计方法来保存日志和分类帐数据。 只保留 Journal 信息,然后 Ledger 只是 Journal 的一个 View (因为 journal 总
我想在另一个子里面有一个子, sub a { sub b { } } 我想为每次调用 sub b 创建一个新的 sub a 实例。有没有办法在 Perl 中做到这一点? 当我运行上面的
我有一些代码正在查找重复项并突出显示单元格: Private Sub cmdDups_Click() Dim Rng As Range Dim cel As Range Set Rng = ThisW
可能有一个简单的解决方案,但我很难过。 我有一个包含一个 ID 字段的主表。在两个可能的字段中有一个具有该 ID 的子表。想象一个由选手 A 和选手 B 组成的 double 队。Master 表将有
假设我有一个包含对象的数组: [ { "id": "5a97e047f826a0111b754beb", "name": "Hogwarts", "parentId": "
我正在尝试对 MySQL 数据库表执行一对父/子模型的批量插入,但似乎无法使用标准的 ActiveRecord 功能来完成。所以,我尝试了 activerecord-import gem,但它也不支持
我有一个带有多个子类的父抽象类。最终,我希望通过 GUI 中的进度条显示子类中完成的进度。 我目前所做的,我意识到这是行不通的,是在父类中声明为每个子类将覆盖的虚拟方法的事件方法定义。所以像: pub
是否可以通过键数组在对象中设置变量?例如我有这个对象: var obj = {'outer': {'inner': 'value'} }; 并希望设置由键数组选择的值: var keys = ['ou
我有一个名为 companies 的 MySQL 表,如下所示: +---------+-----------+-----------+ | id_comp | comp_name | id_pare
我正在尝试使用 sublime text 在 sublime text 上的 ionic 上打开我的第一个应用程序。它给了我一个“找不到命令”的错误。如何修复? 我试过这些命令: sudo rm -r
不好意思问,但我正在使用 webapp2,我正在设计一个解决方案,以便更容易定义路由 based on this google webapp2 route function .但这完全取决于能够在子级
我有代表树的数字字符串(我不知道是否有官方名称): 012323301212 上面的例子代表了 2 棵树。根用 0 表示。根的直接子代为“1”,“1”的直接子代为“2”,依此类推。我需要将它们分组到由
是否可以在当前 Activity 之上添加 Activity 。例如,假设我单击一个按钮,然后它将第二个 Activity 添加到当前 Activity 。而第二个 Activity 只覆盖了我当前
我很难思考如何为子资源建模。 以作者的书籍为例。你可以有 N 本书,每本书只有一位作者。 /books GET /books POST /books/id PUT /books/id DELETE 到
有人可以向我解释以下内容(python 2.7) 来自已解析文件的两个字符串数字: '410.9''410.9 '(注意尾随空格) A_LIST = ['410.9 '] '410.9' in '41
背景 在 PowerShell 中构建 hash table 是很常见的通过特定属性快速访问对象,例如以 LastName 为基础建立索引: $List = ConvertFrom-Csv @' I
我真的很难弄清楚如何调用嵌套 Polymer Web 组件的函数。 这是标记: rise-distribution组件有 canPlay我想从 rise-playlist
我写了一个小工具转储(以 dot 格式)一个项目的依赖关系图,其中所有位于同一目录中的文件都聚集在一个集群中。当我尝试生成包含相应图形的 pdf 时,dot开始哭: 命令 dot -Tpdf trim
给定一个 CODE ref,是否可以: 访问该 CODE ref 的解析树 通过指定 CODE ref 的解析树来创建一个新的 CODE ref,该解析树可以包含在 1 中返回的解析树的元素 通常我们
我是一名优秀的程序员,十分优秀!