Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 核心数据保存竞争条件错误_Multithreading_Ios_Core Data_Concurrency - Fatal编程技术网

Multithreading 核心数据保存竞争条件错误

Multithreading 核心数据保存竞争条件错误,multithreading,ios,core-data,concurrency,Multithreading,Ios,Core Data,Concurrency,我有一个更新应用程序数据的NSOperation。此操作有自己的上下文,更改通过contextDidSave通知传回主线程上的上下文 更新操作删除对象。这些删除操作无意中导致了崩溃。当主线程在保存更新上下文的同时重新加载UITableView时,会发生崩溃。tableview的数据源由一个NSFetchedResultsController支持 CoreData或UIKit均未输出任何日志记录。崩溃是在访问managedObject的属性时在tableView:cellForRowAtIndex

我有一个更新应用程序数据的
NSOperation
。此操作有自己的上下文,更改通过
contextDidSave
通知传回主线程上的上下文

更新操作删除对象。这些删除操作无意中导致了崩溃。当主线程在保存更新上下文的同时重新加载
UITableView
时,会发生崩溃。tableview的数据源由一个
NSFetchedResultsController
支持

CoreData或UIKit均未输出任何日志记录。崩溃是在访问managedObject的属性时在
tableView:cellForRowAtIndexPath:
中发生的信号。以下是成功更新的结果。您可以看到,表格被填充一次,然后上下文被保存,这又导致表格被重新加载:

tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
tableView:cellForRowAtIndexPath: row: 6
tableView:cellForRowAtIndexPath: row: 7
tableView:cellForRowAtIndexPath: row: 8
tableView:cellForRowAtIndexPath: row: 9
Will saved update context
Did saved update context
Will merge update context
tableView:numberOfRowsInSection: rowCount = 58
Did merge update context
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
tableView:cellForRowAtIndexPath: row: 6
tableView:cellForRowAtIndexPath: row: 7
tableView:cellForRowAtIndexPath: row: 8
tableView:cellForRowAtIndexPath: row: 9
下面是崩溃发生时的输出:

tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
Will saved update context
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5

我可以想出两种可能的解决办法:

  • 在刷新表视图时锁定PersistentStoreCoordinator。(这可以通过子类化
    UITableView
    并覆盖
    reloadData
    来实现,以提供锁定和解锁存储的位置)
  • 将删除推迟到以后的日期,例如,当应用程序退出时。(这可以通过向实体添加
    isStale
    attrib或创建新的
    Trash
    实体并向其添加对象来实现。)

  • 然而,这两种解决方案似乎都非常粗糙。我错过什么了吗?我的第一个想法是尝试让
    NSFetchedResultsController
    预取所有对象,但这是不可能的。另一种可能的解决方案是在使用
    控制器idchangeContent:
    时锁定存储,但当fetchedResultsController未触发表重新加载时,仍然会出现问题。

    正如其他人提到的,堆栈跟踪是至关重要的。如果没有,我们只能猜测解决方案。

    @Benedict Cohen控制台和stacktrace上的崩溃显示了什么?你确定你做得对吗?“此操作有自己的上下文,更改会通过contextDidSave通知传回主线程上的上下文。”这部分内容看起来特别狡猾,我已经仔细检查过了,我99%确定我做得对。我已经使用通知和mergeChangesFromContextDidSaveNotification的文档在其他线程中读取并重新读取了跟踪更改:@Benedict Cohen你看过CoreDataBooks的例子吗?似乎有两个陷阱很容易忘记或错过。。此外,您是否在表视图中使用beginUpdate/endUpdate?@Benedict Cohen SIG_ABRT还建议过早释放对象。是否可能有其他对象持有对已删除对象的引用,或已删除对象持有对某个对象的无效引用?从我所看到的情况来看,如果上下文合并失败,您应该得到InternalConsistency异常,而不是SIG_ABRT(我不是100%确定,但值得检查)