2014-11-28 1 views
1

예를 들어 3 개의 비동기 블록이있는 메소드가 있습니다. 각 블록 결과는 최종 블록 결과를 얻기 위해 다음 블록을 수행하는 데 필요합니다. 그래서, 내가 무엇을 찾고있어 엄격한 위해 죽은 잠금비동기 블록 완료 대기

__block id task1Result;  
__block id task2Result;  
__block id finalResult; 

[self startTask1:^(id result) { task1Result = result }] 

[self startTask2:task1Result block:^(id result) { task2Result = result }] 

[self startTask3:task2Result block:^(id result) { finalResult = result }] 

UPD없이 수행 make'em에 좋은 GCD 전략이다. 나는 해결책 발견 :

dispatch_semaphore_t sem = dispatch_semaphore_create(0); 

__block id task1Result;  
__block id task2Result;  
__block id finalResult; 

[self startTask1:^(id result) { 
    task1Result = result; 
    dispatch_semaphore_signal(sem); 
}]; 
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 

[self startTask2:task1Result block:^(id result) { 
    task2Result = result; 
    dispatch_semaphore_signal(sem); 
}]; 
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 

[self startTask3:task2Result block:^(id result) { finalResult = result }]; 

을하지만 내 경우에는 내가 교착하는 응용 프로그램을 제공합니다 일부 라이브러리 방법에 문제에 직면했다. 여기에 설명처럼> <

+0

세마포어를 사용하지 마십시오. 이는 우선 순위 역전으로 쉽게 이어질 수있는 최악의 해결책입니다. 직렬 대기열을 사용하여 작업을 직렬화하십시오. –

+0

내 경우에 내가 어떻게 사용해야하는지에 대한 예제 코드를 줄 수 있습니까? –

+0

직렬 대기열을 작성하고 블록을 제출하십시오. 그들은 순서대로 처형 될 것입니다. dogsgod는 당신에게 아래에보기를 주었다. –

답변

3

직렬 파견 큐를 만듭니다
https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

을 한마디로 :

dispatch_queue_t queue; 
queue = dispatch_queue_create("com.example.MyQueue", NULL); 
dispatch_async(queue, ^{ 
    printf("Do some work here.\n"); 
}); 
dispatch_async(queue, ^{ 
    printf("When finished do next task.\n"); 
}); 

당신이 큐를 직접 처리 할 필요가 있음을 알고 있어야합니다.

+0

dispatch_queue는 좋지만 dispatch_async에서 비동기 API를 호출하면 모든 API 호출을 기다리는 목표를 달성 할 수 없습니다. –

+0

@Claus Jørgensen : 대기열이 연속적이며 한 번에 하나의 작업을 처리합니다. 이것이 왜 충분하지 않은지 당신이 자세히 설명해 주시겠습니까? – dogsgod

+1

'dispatch_async' (anotherQueue,^{})를'dispatch_async' 안에 넣으면 끝내기를 기다리지 않습니다. 그의 작업 API가 GCD에 기반하지 않은 기존 API라고 가정 할 때, 당신의 제안은 아무런 영향을 미치지 않을 것입니다. OP가 기존 API를 호출하는지 여부가 결정됩니다. –

-1

각 작업이 이전 작업의 결과를 직접 사용하는 경우 이전 작업의 완료 콜백에서 각 작업을 시작할 수 있습니까? 그래도 마지막 작업이 완료되기를 기다리려면 파견 그룹이 필요합니다. 당신이로 실행할 수 있습니다

dispatch_group_t group = dispatch_group_create(); 
__block id result; 

dispatch_group_enter(group); 
[self startTask1:^(id task1Result) { 
    [self startTask2:task1Result block:^(id task2Result) { 
    [self startTask3:task2Result block:^(id finalResult) { 
     result = finalResult; 
     dispatch_group_leave(group); 
    }]; 
    }]; 
}]; 

dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 

한 합병증은 완료 핸들러가 작업을가 대기 상태 처리하는 동일한 일련 큐에 호출하는 경우 완료 핸들러에서 작업을 대기열을 시도하는 교착 상태의 위험, 즉 실행 여부입니다.

+0

이 방법은 너무 추합니다. 나는 그것을 제거하고 싶다. –

+0

완료 처리기가 중첩되어 있기 때문에 주로 추악한 경우가 있습니까? – Pivot