iOS 시작 백그라운드 스레드


117

iOS 기기에 작은 sqlitedb가 있습니다. 사용자가 버튼을 누르면 sqlite에서 데이터를 가져 와서 사용자에게 보여줍니다.

이 가져 오기 부분은 백그라운드 스레드에서 수행하고 싶습니다 (UI 메인 스레드를 차단하지 않기 위해). 나는 이렇게한다-

[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];

가져 오기 및 약간의 처리 후 UI를 업데이트해야합니다. 그러나 (좋은 방법으로) 백그라운드 스레드에서 UI 업데이트를 수행해서는 안됩니다. 나는 selector그렇게 메인 스레드를 호출합니다 -

[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];

하지만 내 앱은 첫 번째 단계에서 충돌합니다. 즉, 백그라운드 스레드를 시작합니다. iOS에서 백그라운드 스레드를 시작하는 방법이 아닙니까?

업데이트 1 :[self performSelectorInBackground.... 이 스택 트레이스를 얻은 후 정보가 없습니다.

여기에 이미지 설명 입력

업데이트 2 : 나는 심지어 그렇게 배경 스레드를 시작하려고 시도 [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];했지만 여전히 동일한 스택 추적을 얻습니다.

명확히하기 위해 메인 스레드에서이 작업을 수행하면 모든 것이 원활하게 실행됩니다.

업데이트 3 이것은 배경에서 실행하려는 방법입니다.

- (void)getResultSetFromDB:(NSMutableArray *)toProceessDocids
{
    SpotMain *mirror = [[SpotMain alloc] init];
    NSMutableArray *filteredDocids = toProceessDocids;

    if(![gMediaBucket isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForMediaBucketWithDocID:filteredDocids mBucket:gMediaBucket numRes:-1];
    if(![gMediaType isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForMediaType:filteredDocids mediaType:gMediaType numRes:-1];
    if(![gPlatform isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForPlatformID:filteredDocids platformId:@"1" numRes:-1];

    self.resultSet = [mirror FetchObjectFromDocid:filteredDocids];
    [filteredDocids release];
    [mirror release];

    [self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
    return;
}

어떤 오류 / 충돌 로그가 표시됩니까?
jtbandes

... 내 업데이트를 참조하십시오
Srikar Appalaraju

백그라운드에서 호출하는 방법을 보여줄 수 있습니까? 그리고 개체 docids가 유지 되는지 확인하십시오 .
Rog

예, docids있습니다 retain. 나는 그것을 뒀다 .h@property (nonatomic, retain) NSMutableArray *docids;
Srikar Appalaraju

메소드 앞에 get; 그게되어야합니다resultSetFromDB:
bbum aug.

답변:


270

을 사용 performSelectorInBackground:withObject:하여 새 스레드를 생성하는 경우 수행 된 선택기는 새 스레드의 자동 릴리스 풀, 실행 루프 및 기타 구성 세부 정보를 설정합니다 . Apple의 Threading Programming Guide 에서 "Using NSObject to Spawn a Thread"참조하십시오 .

그래도 Grand Central Dispatch를 사용하는 것이 더 나을 것입니다 .

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self getResultSetFromDB:docids];
});

GCD는 최신 기술이며 메모리 오버 헤드 및 코드 라인 측면에서 더 효율적입니다.


위의 코드를 더 간단하게 만들고 Apple의 최신 GCD 코드 예제를 따라 잡는 변경 사항을 제안한 Chris Nolet 에게 모자 팁으로 업데이트되었습니다 .


멋있는! 이것을 몰랐습니다. 이것은 [NSThread detachNewThreadSelector:@selector....또한 적용됩니까 ?
Srikar Appalaraju

예. Apple 문서에 따르면 performSelectorInBackground:withObject:" 현재 개체, 선택기 및 매개 변수 개체를 매개 변수로 사용하여 의 detachNewThreadSelector:toTarget:withObject:메서드 를 호출 한 것과 동일 NSThread합니다."
Scott Forbes

사이에 차이가 (unsigned long)NULL0이 문제에 대해는?
Sti

4
@Sti from apple Dev Docs : 참고 : dispatch_get_global_queue 함수의 두 번째 인수는 향후 확장을 위해 예약되어 있습니다. 지금은이 인수에 대해 항상 0을 전달해야합니다.
Jawad Al Shaikh 2014 년

그런 다음 performSelectorOnMainThread를 사용하여 작업 결과로 UI를 업데이트해야합니까? 아니면 GCD로 UI를 업데이트하는 더 일관된 방법이 있습니까?
Ilya Denisov 2015

9

실제로 GCD에서는 꽤 쉽습니다. 일반적인 워크 플로는 다음과 같습니다.

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^{
        // Perform async operation
        // Call your method/function here
        // Example:
        // NSString *result = [anObject calculateSomething];
                dispatch_sync(dispatch_get_main_queue(), ^{
                    // Update UI
                    // Example:
                    // self.myLabel.text = result;
                });
    });

GCD에 대한 자세한 내용은 여기에서 Apple 문서를 참조하십시오.


4

사용 NSZombieEnabled을 발표 한 후 액세스되고있는 오브젝트 알고. 그런 다음 그와 관련이 있는지 확인하십시오 getResultSetFromDB:. 또한 docids내부에 무엇이 있는지, 보관 중인지 확인하십시오 .

이렇게하면 잘못된 것이 없는지 확인할 수 있습니다.


메인 스레드에서 원활하게 실행되는 사용 라인을 복사하십시오.
Nicolas S

나는 메인 스레드에서 이것을 사용 및 그것은 갑자기 충돌 대신 그 방법 안타이어야 -[self getResultSetFromDB:docids];
Srikar Appalaraju을

내가 말한 것을 활성화 했습니까?
Nicolas S

이 줄에 중단 점을 넣으십시오. SpotMain * mirror = [[SpotMain alloc] init]; 그 히트인지, 만약 텐이라면 어떤 라인이 충돌하는지 알려주세요. 명확한 오류 로그를 얻을 수 있도록 좀비를 활성화하십시오.
Nicolas S

예, 좀비를 활성화했습니다. 나는 이것을 얻는다-`2011-08-14 12 : 49 : 42.697 FLO [16211 : 707] ***-[FMResultSet release] : 할당 해제 된 인스턴스 0x2bff80으로 보낸 메시지 2011-08-14 12 : 49 : 42.697 FLO [16211 : 1607] *** __NSAutoreleaseNoPool () : 클래스 __NSCFData의 개체 0x2c0cc0이 자리에없는 풀과 오토 릴리즈 - 단지 누출 . Also when I try to call this method from background thread I do not reach 그것은 ... 백그라운드 스레드를 입력 한 후 곧 충돌`... SpotMain * 거울
Srikar Appalaraju

2

iOS와 함께 제공되는 기본 sqlite 라이브러리는 SQLITE_THREADSAFE 매크로를 사용하여 컴파일되지 않습니다. 이것이 코드가 충돌하는 이유가 될 수 있습니다.


2

Swift 2.x 답변 :

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        self.getResultSetFromDB(docids)
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.