2013-06-13 3 views
0

어떻게하면 CPU 100 %를 얻고 백그라운드 스레드에서 주 스레드를 차단할 수 있습니까? 나는 그런 식으로 작업을 수행합니다코어 데이터 작업에서 CPU 100 %

-(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 사용량을 얻었고 인터페이스가 차단되었습니다! 왜?!

+0

메인 저장소와 영구 저장소를 공유하고 있습니까? – Tommy

답변

2

실제로 CPU를 소비하는 코드를 프로파일 링 했습니까?

관리 개체 컨텍스트는 어떻게 구성됩니까? 특히, 동시성 유형은 무엇입니까? 동시성 유형이 NSMainQueueConcurrencyType 인 경우 컨텍스트가 블록을 수행하도록하는 대기열을 사용하면 완전히 무의미합니다.

가까운 this documentation을 읽어 보시기 바랍니다.


세터에서 그 dispatch_async의 사용은 모두 불필요하며 connectionDidFinishWithObject:에서 다른 큐에 사용 dispatch_async과 경쟁 조건으로 이어질 것입니다.

e.e. 동시성이 파기됩니다.

2

디버거에서 실행하고 '일시 중지'를 눌러 메인 스레드가 수행중인 작업을 찾습니다. 인스트루먼츠를 사용하여 CPU를 씹는 코드가 무엇인지 보여줍니다.

+0

Core Data.I에 많은 수의 개체가 삽입되어 있지만이 코드로 주 스레드가 차단 된 이유는 무엇입니까? – Kuba

+0

디버거에서 일시 중지하면 현재 실행 중이거나 주 스레드에서 대기중인 기능을 확인할 수 있습니다. 해당 정보를 게시하면 주 스레드가 차단 된 이유에 대한 질문에 답변 할 수 있습니다. – Bryan

1

나는 모든 경우에, 당신은 어떻게 메인 큐에 코어 데이터를 사용하는에 아직 명확하지 않다,하지만이의 일반적인 원인은 것입니다 : 당신이 SQLite는 영구 저장소를 사용했습니다

  1. ;
  2. 메인 큐의 일부 NSManagedObject 속성에 액세스하고 있습니다.
  3. 동시에 다른 대기열에 저장합니다.

액세스하려는 객체가 현재 잘못 되었기 때문에 메인 대기열에 대한 액세스가 필요합니다. 데이터베이스로의 다른 여행도 문제가 될 수 있습니다. 따라서 NSFetchRequest을 명시 적으로 수행하거나 스크롤로 인해 어떤 작업을 수행해야하는 활성 NSFetchedResultsController을 갖는 것은 모두 동일한 조건입니다.

슬프게도 SQLite는 스레드로부터 안전하지 않습니다. 결과적으로 일부는 저장하는 동안 데이터베이스에 액세스 할 수 없습니다. 저장하는 데 많은 시간이 걸릴 수 있습니다. 많은 항목을 삽입했거나, 복잡한 색인이 있거나, 다른 이유로 인해 많은 시간이 걸릴 수 있습니다.

따라서 메인 대기열은 데이터베이스로의 동기 이동을 원하지만 코어 데이터는 저장이 완료 될 때까지 대기해야합니다. 그러므로 그것은 막아야한다.