核心数据操作中的100%CPU

时间:2013-06-13 17:24:36

标签: ios objective-c multithreading core-data

我如何获得CPU 100%并阻止后台队列中的主线程。我这样做:

首先,我在自定义setter中创建上下文:

-(void)setContext:(NSManagedObjectContext *)context {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        _context = context;
    });
}

然后我使用NSURLConnectionDataDelegate下载一些数据,然后是我插入的方法:

-(void)connectionDidFinishWithObject:(NSArray*)arrayOfObjects {

    dispatch_queue_t fetchQ = dispatch_queue_create("myDispatch", NULL);
    dispatch_async(fetchQ, ^{
                [self.context performBlock:^{
                    for(NSDictionary *dic in myArr) {
                        [Tournament  tournamentWithDictionary:dic inMOC:self.context];
                    }
                }];
            }

}

这是我对NSManagedObject子类的插入:

+(Tournament*)tournamentWithDictionary:(NSDictionary*)dictionary inMOC:(NSManagedObjectContext*)moc {
 Tournament *finalElement;   

    if(!finalElement) {
        finalElement = [NSEntityDescription insertNewObjectForEntityForName:@"Tournament" inManagedObjectContext:moc];
        [finalElement setTournamentID:[NSNumber numberWithInt:[[dictionary objectForKey:@"ID"] integerValue]]];
    }
    return finalElement;
}

我获得了100%的CPU使用率并且我的界面是阻止的!为什么呢?!

3 个答案:

答案 0 :(得分:2)

在调试器下运行并点击“暂停”以找出主线程正在做什么。使用Instruments来显示正在运行的代码来咀嚼CPU。

答案 1 :(得分:2)

您是否真的对代码进行了分析以查看消耗CPU的内容?

另外,您的托管对象上下文是如何配置的?具体来说,什么是并发类型?如果并发类型是NSMainQueueConcurrencyType,那么使用队列来导致上下文执行块将完全没有意义。

我建议你仔细阅读this documentation


您在setter中使用dispatch_async是不必要的,并且dispatch_async使用connectionDidFinishWithObject:不同的队列会导致竞争条件}。

即。你的并发性被破坏了。

答案 2 :(得分:1)

我还不清楚你是如何在主队列上使用核心数据的,如果有的话,但通常的原因是:

  1. 您使用过SQLite持久性商店;
  2. 您正在访问主队列中的某些NSManagedObject属性;
  3. 同时您正在保存其他队列。
  4. 对主队列的访问需要访问数据库,这通常是因为您正在访问的对象当前是一个错误 - 尽管任何其他数据库之旅都会有问题。因此,明确地执行NSFetchRequest或具有必须执行某些工作的活动NSFetchedResultsController,因为滚动都是等效条件。

    可悲的是,SQLite不是线程安全的。部分结果是您在保存时无法访问数据库。如果您插入了大量条目,如果您有复杂的索引,或者出于其他一些原因,保存可能需要很长时间。

    因此主队列需要同步到数据库,但Core Data必须等待保存完成。因此它必须阻止。