3

내 응용 프로그램에서는 여러 소스의 데이터를로드하고 테이블보기로 모아야합니다. 각 소스를 하나씩 수집하는 것이 영원히 걸릴 것입니다. 이 문제를 해결하려면 모든 다운로드 작업을 함께 실행해야합니다. 그것들은 다운로드 작업이므로 이론적으로는 그냥 실행할 수 있지만 문제는 스레드의 코드 부분 만 비동기 적으로 실행된다는 것입니다. 즉, 작업을 완료하기 위해 주 스레드가 필요할 것입니다.iOS- 여러 동시 작업 관리 및 추적

그래서 모든 것을 백그라운드에서 실행하려면 GCD를 사용해야합니다. GCD는 많은 경험이 필요하지 않습니다.

//DataLoader.m 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 
    [self.webLoader getFeedWithCompletion:self.thatOtherCompletionBlock]; 
    [self.otherDataLoader getDataWithCompletion:self.completionBlock]; 
    [self.thatDataLoader getThatDataWithCompletion:self.anotherCompletionBlock] 
    dispatch_async(dispatch_get_main_queue(), ^(void){ 

    }); 
}); 

그러나 작업의 일부가 이미 비동기 적이기 때문에 GCD 코드를 어디에 넣어야하는지 파악해야합니다.

나는 위에서 한 것처럼 작업을 시작하기 전에 그것을 넣을 수 있습니다. 그러나 작업이 이미 백그라운드에서 부분적으로 실행 되었기 때문에 (일부 경우에는 변경할 수 없음) 백그라운드에서 백그라운드로 실행되는 작업을 낭비하는 것처럼 보입니다. 다른 스레드의 백그라운드 스레드에서 이미 실행되는 것을 실행해야하는 이유는 무엇입니까?

또 다른 옵션은 배경

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 
    ....... 

}); 

더 나은 방법으로 실행되지 않는 모든 코드에 퍼팅 피드 (예. webloader)를 얻는 실제 수업 시간에 GCD를 사용하는 것입니다?

또 다른 문제가 있습니다. 일부 작업은 비동기식이므로 완료 블록을 사용합니다. 백그라운드에서 완료 블록을 실행할 필요가있을뿐만 아니라 어느 것이 마지막으로 완료되어야하는지 파악해야하므로 일부 코드를 실행하여 정리하고보기 컨트롤러에 데이터를 깔끔하게 패키징하고 제공 할 수 있습니다.

내가 생각한 방식은 각 작업에 BOOL을 사용하는 것이고, 작업이 완료되면이를 true로 변경하는 것입니다. 그런 다음 완료 블록에서 다른 모든 작업이 완료되었는지 확인할 수 있습니다. 그렇다면 정리 코드를 실행하십시오. 그러나 이것은 가장 우아한 해결책이 아닐 수도 있습니다.

이러한 작업을 처리하고 백그라운드에서 모든 작업을 수행하는 가장 좋은 방법은 무엇입니까?

+0

비동기 코드가 이미 작동하고 있다면 아마도 동시 NSOperation을 사용하는 것이 가장 좋습니다. –

답변

5

GCD 그룹을 쉽게 사용할 수 있습니다. 그룹을 사용하면 그룹의 임의 "구성원"을 추적 할 수 있으며 그룹의 모든 구성원이 끝나면 블록을 실행하여 실행시킬 수 있습니다. 아주 편리합니다.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 
    dispatch_group_t group = dispatch_group_create(); 

    dispatch_group_enter(group); // + 1 
    [self.webLoader getFeedWithCompletion: ^{ 
     self.thatOtherCompletionBlock(); 
     dispatch_group_leave(group); // - 1 
    }]; 

    dispatch_group_enter(group); // + 1 
    [self.otherDataLoader getDataWithCompletion:^{ 
     self.completionBlock(); 
     dispatch_group_leave(group); // - 1 
    }]; 

    dispatch_group_enter(group); // + 1 
    [self.thatDataLoader getThatDataWithCompletion:^{ 
     self.anotherCompletionBlock(); 
     dispatch_group_leave(group); // - 1 
    }]; 

    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // This will get executed once all three of the prior completion blocks have been run. 
     // i.e. when the group "count" goes to zero. 
    }); 

    dispatch_release(group); 
}); 

또한, 조금 circuitously 불구하고,이를 달성하기 위해 NSOperation의 간 작업 종속성 기능을 사용할 수 있습니다 : 예를 들어 (코드 사용). 이처럼 :

NSOperationQueue* q = [[[NSOperationQueue alloc] init] autorelease]; 

NSOperation* completionA = [NSBlockOperation blockOperationWithBlock: self.thatOtherCompletionBlock]; 
NSOperation* completionB = [NSBlockOperation blockOperationWithBlock: self.completionBlock]; 
NSOperation* completionC = [NSBlockOperation blockOperationWithBlock: self.anotherCompletionBlock]; 

NSBlockOperation* afterAllThree = [[[NSBlockOperation alloc] init] autorelease]; 
[afterAllThree addDependency: completionA]; 
[afterAllThree addDependency: completionB]; 
[afterAllThree addDependency: completionC]; 
[afterAllThree addExecutionBlock:^{ 
    // This will get executed once all three of the prior completion blocks have been run. 
}]; 

// Kick off the tasks 
[q addOperationWithBlock:^{ 
    [self.webLoader getFeedWithCompletion: ^{ [q addOperation: completionA];}]; 
    [self.otherDataLoader getDataWithCompletion:^{ [q addOperation: completionB]; }]; 
    [self.thatDataLoader getThatDataWithCompletion:^{ [q addOperation: completionC]; }]; 
}]; 

는 개인적으로 dispatch_group 방법을 선호하지만, 그들은 모두 작업을 끝낼 것입니다.

+0

이 3 개의 블록 중 하나에 다른 비동기 블록이있는 경우 어떻게됩니까? 예상대로 계속 작동할까요? HELP –

+0

너는 나에게 더 많은 것을 주어야 할 것이다. 또는 더 나은 아직, 그냥 새로운 질문을 부탁드립니다. – ipmcc