2016-10-21 2 views
2

오늘을 일시 :직렬 큐에게 나는 다음 코드를 시도했습니다

- (void)suspendTest { 
    dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_BACKGROUND, 0); 
    dispatch_queue_t suspendableQueue = dispatch_queue_create("test", attr); 
    for (int i = 0; i <= 10000; i++) { 
     dispatch_async(suspendableQueue, ^{ 
      NSLog(@"%d", i); 
     }); 
     if (i == 5000) { 
      dispatch_suspend(suspendableQueue); 
     } 
    } 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     NSLog(@"Show must go on!"); 
     dispatch_resume(suspendableQueue); 
    }); 
} 

코드는 10001 작업을 시작하지만 중간 육초에 재개 새 작업을 실행 한 큐를 일시 중단합니다. 이 코드 은 예상대로 작동합니다. - 5000 개의 작업이 실행 된 다음 대기열이 중지되고 6 초 후에 다시 시작됩니다. 그러나 동시 대기열 대신 직렬 대기열을 사용하면 그 동작이 나에게 명확하지 않습니다. 태스크 난수 중단하기 전에 실행 관리 이때

dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_BACKGROUND, 0); 

하지만, 종종이 수가 0에 가까운 (현탁 어떤 작업이 발생하기 전에). 질문입니다 - 직렬 및 동시 대기열에 대해 일시 중단 작동이 다른 이유와 직렬 대기열을 올바르게 일시 중단하는 방법은 무엇입니까?

+1

게시 한 코드가 컴파일되지 않습니다. 'if (i == 5000) {'줄은'for' 루프 뒤에 있습니다. – rmaddy

+0

내 잘못으로, 방금 메모리로 재생산했습니다. 내가 고치자 –

+2

그래,이게 진짜 코드를 브라우저에 붙여 넣지 않는 질문 중 하나 야? 나는 그걸 막을 수 없다. – matt

답변

1

이름에 따라 직렬 대기열은 일련의 작업을 수행합니다. 즉, 이전 작업이 완료된 후 다음 작업부터 시작합니다. 우선 순위 클래스는 백그라운드이므로 현재 대기열이 5000 번째 작업에 도달 할 때까지 첫 번째 작업에서 시작하지 않고 대기열을 일시 중단 할 수 있습니다. dispatch_suspend의 문서에서

:

서스펜션은 호출시 실행되는 블록의 완료 후에 발생합니다.

즉, 아무는 그 비동기 완료 할 큐에서 작업을 파견 약속하지 않는, 어떤 현재 작업 (블록)를 실행하는 것만은 통해 파트 방법을 중단하지 않습니다. 직렬 대기열에서 최대 하나의 작업은 "현재 실행 중"일 수 있지만 동시 대기열에서는 지정된 상한이 없습니다. 편집 : 그리고 100 만 건의 작업을 테스트 한 결과에 따르면 동시 대기열은 "완전히 동시 적"이라는 개념적 추상화를 유지하고 실제로 존재하지 않더라도 "현재 실행 중"이라고 간주합니다.

5000 번째 작업 이후에 작업을 일시 중단하려면 5000 번째 작업에서이 작업을 트리거 할 수 있습니다. (그러면 일시 중지 된 시간부터 이력서 타이머를 시작하고 싶지 않을 수도 있습니다. 그렇지 않으면 이론적으로는 이력서가 일시 중지되기 전에 다시 시작하면 이론적으로 다시 시작할 수 없습니다.)

+0

그러면 동시 대기열이 동일한 우선 순위를 갖는 시계와 같이 실행되는 이유는 무엇입니까? –

+1

@AleksandrMedvedev 정말 중요하지 않습니다. API는 사용자가 기대할 수있는 것을 지정하며 직렬 대기열이 원하는 방식으로 작동하도록 기대할 수 없습니다. 직렬 큐는 "현재 실행중인"하나의 작업 만 고려하는 반면, 동시라고 생각하기 때문에 모든 디스패치 작업을 "현재 실행 중"으로 처리하고 완료 할 수 있습니다. – Arkku

+0

@AleksandrMedvedev 동시 대기열로 작업의 수와 길이를 늘리면 흥미로운 실험이 될 수도 있습니다. 50,000 명을 파견하고 각각 더 많은 일을한다면 여전히 효과가 있습니까? – Arkku

1

나는 문제가 있다고 생각합니다. suspendbarrier을 혼동스럽게합니다. suspend은 큐를 막습니다. 입니다. barrier은 장벽이 실행되기 전에 대기열에있는 모든 항목이 중지되면 중지됩니다. 따라서 5000 번째 작업 후에 장벽을 설치하면 직렬 대기열의 장벽에서 일시 중지하기 전에 5000 개의 작업이 실행됩니다.

+0

제안 해 주셔서 감사합니다. 나는 '장벽'에 대해 알고 있지만 문제는 해결책과 관련이 없다. 나는 그것이 어떻게 작동하는지, 그리고 일시 중단 및 동시 대기열 측면에서 "이미 실행중인 작업"을 의미하는 것에 관심이 있습니다. 어쨌든 당신의 노력은 감사하겠습니다. –

관련 문제