2012-10-12 140 views
2

我有一个iOS应用程序,从Web服务拉下用户数据,并将其保存到sqlite支持的核心数据存储。虽然这也正在进行,我正在为用户的头像提供url,并将图像保存到核心数据中,因为每个图像的下载都可用。解决核心数据死锁问题?

这些都是在自己的线程上使用自己的托管对象上下文执行的,但使用相同的共享持久性存储协调器。

当只有几件物品被拉下时,这个效果很好,但当我们接近100件物品时,我在初始数据加载时频繁死锁。当我暂停调试器时,我看到不同的线程通常都在等待executeFetchRequest。

我打开了我的方案中的sql调试,并根据控制台输出提取完成,但线程永远不会继续。

我还有什么可以使用或看看为什么这些是死锁或我如何可以防止这些死锁发生?

+1

的一件事是,如果你遇到这种死锁的同时调试Xcode中(我确实经常),则可以暂停调试器,看到一个堆栈跟踪,往往是非常有用的(你会看到哪个线程是挂在什么功能)。 – borrrden

回答

2

确保你批量更改DB在一起。每次更改后无需调用saveContext。相反,在每十次左右更改之后,保​​存临时背景环境可能就足够了。

请参阅一些指针,这篇文章我的:http://www.cocoanetics.com/2012/07/multi-context-coredata/我想与大家分享

+1

与异步储蓄父/子视图控制器使用的文章真的帮助。 – adam0101

2

要回答您的确切问题:“我还有什么可以用来研究为什么这些是僵局或我怎样才能防止这些僵局发生?”,我只能回答一些非常简单的想法一般是因为你接近的问题很难:

  • 从你认为可能发生锁定的任何地方添加NSLog语句。我发现使用NSLog(@"%s ...YOUR DEBUG STATEMENT", __PRETTY_FUNCTION__)可以帮助您确切地确定哪个函数被调用,以及从哪个队列执行。

如果我们超越什么工具都可以(这基本上是没有什么用处)的问题,那么我留下了有关如何调试你描述的系统中的一些建议:

由于一些背景知识:我用2000多个动态下载和显示的平滑滚动UITableViews动态下载并显示可变高度的单元格,其中包含完全没有由于数据处理或绘图而导致的抖动或延迟的图像。这个系统最初是使用CoreData设计的,但最终我们转向直接使用SQLite来解决您遇到的多线程和并行性问题。我不主张切换到SQLite--这是我们在内部做出的决定,以提高速度并减少本地数据库中的不一致性。我将其作为我的答案的背景。

我会首先看看你使用Grand Central Dispatch。如果您使用任何dispatch_sync调用,请确保它们不会出现在阻塞运行线程的链中。我最初是这样做的,以确保多个线程不会同时访问某个托管对象上下文,并且在几个小时的调试后才发现问题。这些可以偷偷靠近你,因为dispatch_sync调用可能在其他函数调用的函数中很深。

我确实最终使用了一个事务性系统(非常SQL-y),它具有动态创建的单个查询/更新队列,可以确保一次不会发生太多操作。我也有一个完全不同的系统,它会使用一个单独的串行读队列来快速读取数据库。如果可能,该队列的MOC将从其他MOC镜像。这很沉重,而且比较慢。由于该系统主要在后台线程上处理,因此与用户隔离。

CoreData通常很难多线程化。 SQLite稍微简单一些,不过你必须围绕它构建大量的特定于应用程序的体系结构才能使其可用。

如果您想发布有关系统的其他细节,我也许能帮助更具体。希望这有用。