当线程在保存时被杀死时,如何防止 NSManagedObjectContext 损坏数据库?

Posted

技术标签:

【中文标题】当线程在保存时被杀死时,如何防止 NSManagedObjectContext 损坏数据库?【英文标题】:How to prevent NSManagedObjectContext from corrupting the database when a thread gets killed while saving? 【发布时间】:2011-06-01 21:27:08 【问题描述】:

In this question, octy wrote:

顺便说一句,如果您保存在背景上 线程,你还需要考虑什么 当您的应用程序终止时发生 正在进行保存操作时。 后台线程被正确杀死 离开,而看门狗等待 5 主线程完成的秒数 起来。

现在我整天都在实现 NSOperation 并直接在 NSOperation 子类中创建 NSManagedObjectContext 实例,因此每个 NSOperation 都拥有自己的非共享 MOC。但现在这是一个非常坏的消息,因为这样的场景可能一直在发生,会破坏 Core Data 数据库。我的意思是它不能开始在 sqlite3 文件中写入半字节的内容,然后立即停止。

然后还有另一个问题:在我的 NSOperations 中,我还使用 NSFileManager 进行文件 I/O。

那我该怎么办呢?我必须在我的应用程序中跟踪所有正在运行的 NSOperations 和 NSOperationQueues 并在应用程序终止时在 App Delegate 中快速处理它们,以便我可以将 NSOperations 告诉 SFF(快速保存 F*****g)或取消所有操作,抓住他们的 MOC 并立即“硬保存”它们?解决此问题的最佳做法是什么?

为什么我在职业生涯中第一次听到这个消息?我的意思是 NSOperationQueue 和 Core Data 提到的书籍都没有提到这一点,但它似乎是一个随机的应用程序杀手,如果我们不明确注意这一点,它会迫使用户重新安装(并可能丢失大量数据)。

【问题讨论】:

我开发了这个 NSOperation 子类来做你所说的github.com/veritech/FRCoreDataOperation。在我的应用程序的平均运行期间,我将创建超过 100 个在串行 NSOperationQueue 中运行的应用程序。每当应用程序终止/后台运行时,我都会取消所有操作,并且我从未遇到过损坏问题。随意查看课程,也许它可能会对您有所帮助。 您必须在保存操作的中间取消它,因为它可能在现实中发生。这才是真正的问题。 【参考方案1】:

MOC 的主要功能是表示一种独立于格式的抽象存储。它将所有对象存储在内存中,并使用事务机制来提交任何更改。因此,当您在 MOC 中插入/删除/编辑某些对象时,它们仅在内存中更改,而不在持久存储中更改(无论是 SQLite 数据库、XML 文件还是其他)。只有调用save: 方法时才会提交更改。

至于 NSOperation 和文件处理:如果你想停止某些操作,你应该为此调用cancel。来自文档:

此方法不会强制您 操作码停止。相反,它 将对象的内部标志更新为 反映状态的变化。如果 操作已经结束 执行,此方法无效。 取消正在执行的操作 当前在操作队列中,但是 尚未执行,使其成为可能 从队列中删除操作 比平时早。

这意味着如果在取消操作时有一些 IO 操作正在运行,操作会一直等到它完成。

此外,尽管有 Core Data 事务机制,但您应该为不受它管理的任何数据(如果需要)实施自己的机制。

【讨论】:

我的问题不够清楚:当线程被杀死并且 MOC 正在保存时,这不会损坏数据库吗?当线程(MOC 正在运行的线程)从一个纳秒到另一个被杀死时,MOC 如何保存到存储而不破坏其完整性或数据? 保存过程也是一个事务。因此,如果它在执行期间被取消,那么所有更改都将被丢弃,并且不会损坏任何内容。

以上是关于当线程在保存时被杀死时,如何防止 NSManagedObjectContext 损坏数据库?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 EntityFramework 4.1 CodeFirst 防止十进制值在保存时被截断为 2 位? [复制]

iphone - 如何防止应用程序在下载数据时被阻止[关闭]

如何在应用程序被任务管理器杀死时保存数据?

Swift:如何防止未显示的 UITableViewCells 在滚动时被关闭

Objective-C多线程,当一个对象在其方法被执行时被释放会发生啥? (以及如何预防?)

前台服务在执行互联网相关操作时被杀死