当核心数据同时从后台线程和主线程访问时,应用程序崩溃

时间:2012-05-30 15:16:36

标签: objective-c ios core-data grand-central-dispatch

我的情况是我的应用程序使用核心数据,并且需要从该核心数据加载图像以在表格视图中显示。由于需要花费时间,因此需要在后台线程中运行。所以我有这样的代码:

dispatch_async(queue, ^{

    if (self.cellInfo.numberOfMediaItems > 0) {

        int i = 0;

        int numberOfThumbnails = MIN(self.cellInfo.numberOfMediaItems, 3);

        while (i < numberOfThumbnails) {
            Media *media = [self.entry.media objectAtIndex:i];

            UIImage *image = [media getThumbnail];
            [self.mediaArray addObject:image];
            i++;
        }
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        self.isFinishedProcessing = YES;

        [self setNeedsDisplay];
    });

});

这会大大加快处理速度,并且图像在准备就绪时会显示在背景中。

问题是,有时它会让前台线程尝试并在后台线程的同时访问核心数据。它不喜欢这样,所以它崩溃了。这必须是许多开发人员进入的情况,因此需要一个解决方案。我想知道如何处理这种情况,以便我们的应用程序在同时开始访问核心数据时停止崩溃?

2 个答案:

答案 0 :(得分:6)

See my previous answer here

  

核心数据是一个黄金法则 - 一个托管对象   每线程的上下文。托管对象上下文不是线程安全的,所以如果   你正在后台任务中工作,你要么使用主线程   避免与UI操作发生线程冲突,或者创建新的   工作的上下文。如果工作需要几秒钟   然后你应该做后者来阻止你的UI锁定。

简而言之,您需要创建一个单独的托管对象上下文,以便在后台线程中使用。然后,您必须在适当的时候将更改合并回原始上下文。

答案 1 :(得分:1)

您需要阅读Apple的核心数据编程指南。

基本上,NSManagedObjects和NSManagedObjectContexts不是线程安全的。您需要在后台上下文中创建一个新的NSManagedObjectContext来完成工作。您不能跨线程传递NSManagedObjects。相反,您可以存储一个NSManagedObjectID数组,并使用它来从新上下文“重新加载”对象。