【问题标题】:100% CPU in Core Data operation核心数据操作中的 100% CPU
【发布时间】:2013-06-14 04:22:36
【问题描述】:

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

首先我在自定义设置器中创建上下文:

-(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 使用率并且我的界面被阻塞了!为什么?!

【问题讨论】:

  • 您是否与主线程共享持久存储?

标签: ios objective-c multithreading core-data


【解决方案1】:

您是否确实分析过您的代码以查看消耗 CPU 的内容?

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

我建议你仔细阅读this documentation


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

即你的并发被破坏了。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我知道这是插入到Core Data。我有很多对象,但是为什么主线程被这段代码阻塞了?
    • 如果您在调试器中暂停,您将看到哪个函数当前正在主线程中运行或等待。如果您发布该信息,我们或许能够回答您关于主线程为何被阻塞的问题。
    【解决方案3】:

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

    1. 您使用过 SQLite 持久存储;
    2. 您正在访问主队列上的一些 NSManagedObject 属性;
    3. 同时,您正在保存其他队列。

    对主队列的访问需要访问数据库,这通常是因为您正在访问的对象当前出现故障——尽管任何其他访问数据库都会出现问题。因此,明确地执行NSFetchRequest 或拥有一个必须做一些工作的活动NSFetchedResultsController,例如,由于滚动都是等效的条件。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2015-03-11
      • 1970-01-01
      • 2012-05-20
      相关资源
      最近更新 更多