2012-07-31 2 views
0

블록을 현재 대기열의 끝에 추가하고 대기열의 기존 항목이 모두 호출 된 후에이 블록이 호출되도록 할 수 있습니까?이전의 모든 대기열 항목이 완료 될 때까지 블록 실행 금지

아래 코드는 작동하지 않습니다

- (void)someTaskWillBeDoneOnThisThreadLater { 
    // The current scope is a delegate method of a library I'm using, 
    // and unfortunately the required task gets executed after this delegate 
    // method is called. 

    // wait for current queue to be done with everything, including the current scope 
    dispatch_async(dispatch_get_current_queue(), ^{ 
     // After everything is done, then call the main thread 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // Perform some task on main thread 
     }); 
    }); 
} 

편집 : 다음 코드는 문제를 해결하지만, 난 정말 일초 지연에 의존하지 않으려는

. 나는 오히려 더 나은 해결책을 찾는다. dispatch_barrier_async 문서에서

dispatch_async(dispatch_get_global_queue(0, 0), ^{ 

        dispatch_async(dispatch_get_main_queue(), ^{ 
         sleep(1); 
         // Perform something on main thread 
        }); 
       }); 
+1

어떤 종류의 대기열에 대해 이야기하고 있습니까? 직렬 대기열에서 작동해야하므로 동시에 하나의 대기열을 확보 할 수 있습니까? – Tommy

+0

정말 확신 할 수 없다.이 프레임 워크의 소스 코드에 액세스 할 수 없다. – aryaxt

답변

0

: 배리어 블록 전용 동시 대기열의 앞쪽에 도달하면

..., 그것은 즉시 실행되지 않는다. 대신 큐는 이 실행될 때까지 기다렸다가 현재 실행중인 블록이 실행을 마칩니다. 이 시점에서 차단 블록이 단독으로 실행됩니다. 차단 블록 이후에 제출 된 모든 차단은 차단 블록이 완료 될 때까지 실행되지 않습니다.

코드에서 dispatch_asyncdispatch_barrier_async으로 바꾸는 것은 원하는 것을해야합니다.

편집 :

이 또한 @ Johnnywho의 대답은 다음과 같은 의견을 참조, 개인 (동시) 큐에서만 작동합니다.

설명서의 해당 부분을 간과했습니다.

+0

dispatch_barrier가 작동하지 않아 큐가 동시 큐라고 생각한다. – aryaxt

+0

'dispatch_barrier_async'는 작동하지만'dispatch_queue_create ("test", DISPATCH_QUEUE_CONCURRENT)'로 생성 된 개인 동시 대기열에서만 작동합니다. 전역 대기열에서'dispatch_async'와 같이 동작합니다. 나는 내 대답을 편집 할 것이다. –

0

실제로 문제가 발생했는지는 확실하지 않지만 GCD에는 OS X 10.7 또는 iOS 4.3부터 사용할 수있는 기능이 있습니다 (dispatch_barrier_async()).

이 기능을 사용하여 큐에 블록을 제출하면 이전의 모든 블록이 완료 될 때까지 해당 블록이 실행을 대기하게됩니다. 마찬가지로 모든 후속 블록은 장벽이 완료 될 때까지 대기합니다.

동시 대기열과 관련이 있습니다. 직렬 대기열의 특성은 이전에 제출 된 모든 블록이 완료 될 때까지 어떤 블록도 실행을 시작하지 않기 때문입니다.

2

저는이 문제를 해결하기 위해 개인 큐가 필요하다고 생각합니다. 이 코드 :

dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    NSLog(@"FIRST"); 
    dispatch_async(dispatch_get_current_queue(), ^{ 
     NSLog(@"LAST"); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // ... 
     }); 
    }); 
    sleep(2); 
    NSLog(@"SECOND");   
}); 

을 제공합니다 : 당신이 원하는 것이 아니다

2012-07-31 22:57:20.005 Objective-C App[22526:1703] FIRST 
2012-07-31 22:57:20.009 Objective-C App[22526:2003] LAST 
2012-07-31 22:57:22.010 Objective-C App[22526:1703] SECOND 

합니다. 심지어 dispatch_barrier_async도 도움이되지 않습니다.하지만 개인 큐를 사용할 때 : 보시다시피

2012-07-31 23:04:41.882 Objective-C App[22564:1703] FIRST 
2012-07-31 23:04:43.887 Objective-C App[22564:1703] SECOND 
2012-07-31 23:04:43.889 Objective-C App[22564:1703] LAST 

는 "LAST"마지막에 인쇄됩니다이를 이미 블록 때까지 초 정도 기다린 것입니다 :

dispatch_queue_t queue = dispatch_queue_create("test", 0); 
dispatch_async(queue, ^{ 
    NSLog(@"FIRST"); 
    dispatch_async(queue, ^{ 
     NSLog(@"LAST"); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // ... 
     }); 
    }); 
    sleep(2); 
    NSLog(@"SECOND");   
}); 

당신은 당신이 원하는 결과를 줄 것이다 대기열이 완료됩니다.

+0

2 초 지연없이 할 수 있다면 완벽 할 것입니다. – aryaxt

+0

@Johnnywho : 이제는 "dispatch_barrier_async조차도 도움이되지 않습니다"라는 귀하의 의견에 맞습니다. 그 이유는'dispatch_barrier_async'는 private 동시 큐에서만 사용될 수 있고, 그렇지 않으면'dispatch_async'처럼 동작합니다. OP는 어떤 대기열에 함수가 호출되는지 알지 못하기 때문에 많은 도움이되지 않습니다. –

+0

@aryaxt 지연은이 솔루션의 일부가 아닙니다! sleep (2) ** 시뮬레이션 만 표시 ** 긴 태스크는 대기열에있는 모든 이전 작업을 완료하기 위해 2 초 기다린다. – Johnnywho

관련 문제