2014-06-19 2 views
4

NSOperationQueue 자식 작업 잔뜩있는 대기열이있는 NSOperation이 있습니다.NSOperation. 취소 대 완료 상태

대기열에서 cancelAllOperations를 호출 한 후에도 내 기본 메소드가 waitUntilAllOperationsAreFinished에 걸려있는 문제가있었습니다.

그런 다음 취소시 isFinished에 사용하는 전체 플래그를 설정하면 더 이상 취소 된 큐에 백업되지 않습니다.

- (BOOL)isFinished 
{ 
    return complete; 
} 

- (void)cancel 
{ 
    cancelled = YES; 
    complete = YES; 
    [_childOperationQueue cancelAllOperations]; 
} 

이것은 올바른 동작입니까? 취소 된 작업은 기술적으로 완료되어야합니까? NSOperation이 isFinished를 제거하기 전에 true로 설정해야하는 것처럼 보입니다. 생각해볼 때 '정리'가 가능할 수도 있지만 프로토콜이 여기에 있고 Google이 많이 알려지지 않았 음을 알 수 없습니다.

+0

작업이 실제로 취소 되었습니까? 취소하도록 지정하면 즉시 취소되지 않고 블록을 알려주고 취소해야합니다. 실제로'self.cancelled'를 확인하고 작업을 중단해야합니다. 'isFinished' 또는'cancel'을 오버라이드해서는 안되며, 양쪽 모두의 기본 동작이 작동해야합니다. –

+1

@AbhiBeckert 비 동시 작업을 작성하는 경우 올바른 것입니다. 그러나 동시 작업을 작성할 때 항상 isFinished 메소드를 무시합니다 (명시 적으로 또는 자동으로 합성 된 getter로). 또한'cancel'을 다시 쓰면, 일반적으로 그것을 오버라이드하지 않는다는 것에 동의하는 반면, 주기적으로'isCancelled'를 체크하고, 때때로 그것을 할 수 없다는 것에 동의합니다. 예를 들어 블록 기반의 'NSURLSessionTask'를 시작하면'isCancelled'를 확인할 수있는 곳이 없기 때문에 그 시나리오에서'cancel' 메소드를 오버라이드 할 것입니다. – Rob

답변

2

작업을 취소하면 isCancelledYES을 반환합니다. 즉, NSOperation 블록에서 isCancelled을 확인하고 불필요하게 작업하는 것을 방지 할 수 있습니다 (이 논리를 직접 구현해야 함).

주 스레드가 대기열의 모든 작업을 기다려야하지만 NSOperation 블록이 수행하기 전에 isCancelled을 확인하면 대기열에있는 모든 작업을 신속하게 처리해야하며 대기 시간이 길어서는 안됩니다.

+0

블록이 취소되었지만 아직 실행을 시작하지 않았다면 실행이 시작되지 않습니다. 즉, 즉시 "완료"로 변경되어야합니다. –

+1

정말입니까? 나는 그것이 여전히 처형 될 것이라고 생각했고 그것이 취소되었는지를 확인하는 것이 귀하의 임무입니까? –

+1

문서는 실행해서는 안된다고 제안하는 것처럼 보이지만 내 경험으로는 맹세합니다. 주 스레드가 대기열에있는 모든 것을 기다리는 것을 차단했다는 사실이이 작업에 영향을 미칠지 궁금합니다. –

2

당신이 동시 작업을 작성하는 경우 (즉, isConcurrent 방법 YES을 반환), 나는 두 가지 관측이있다 : 당신이 당신의 작업의 상태가 완료 될 변경할 때

  1. , 수동으로 적절한을 수행해야 isFinished KVN. 따라서 상태 변수를 변경하기 전에 willChangeValueForKey으로 전화를 걸고 변경 한 후에는 didChangeValueForKey으로 전화하십시오.

    이를 달성하기 위해 여러 가지 방법이 있습니다,하지만 난 그렇게처럼 내 finishedexecuting 속성을 정의 : 해당 KVN 할 setter를

    @property (nonatomic, readwrite, getter = isFinished) BOOL finished; 
    @property (nonatomic, readwrite, getter = isExecuting) BOOL executing; 
    

    그리고 그 합성 게터를 사용하지만, 쓰기 :

    @synthesize finished = _finished; 
    @synthesize executing = _executing; 
    
    - (void)setExecuting:(BOOL)executing 
    { 
        if (_executing != executing) { 
         [self willChangeValueForKey:@"isExecuting"]; 
         _executing = executing; 
         [self didChangeValueForKey:@"isExecuting"]; 
        } 
    } 
    
    - (void)setFinished:(BOOL)finished 
    { 
        if (_finished != finished) { 
         [self willChangeValueForKey:@"isFinished"]; 
         _finished = finished; 
         [self didChangeValueForKey:@"isFinished"]; 
        } 
    } 
    

    그런 다음 작업을 완료하려면 다음과 같은 메서드를 호출합니다.

    - (void)completeOperation 
    { 
        self.executing = NO; 
        self.finished = YES; 
    } 
    

    그러면 KVN이 isExecutingisFinished이됩니다 (물론 합성 된 getter가 적절한 값을 반환합니다). 이 작업을 수행하지 않으면 작업이 완료되지 않을 수 있습니다. 작업을 취소하는 측면에서

  2. , 두 가지 방법이있다 : 당신은 루프 또는 반복적으로 호출, 예를 들면되고있는 몇 가지 방법이있는 경우

    • 당신은 정기적으로 [self isCancelled] (매우 일반적인 패턴을 확인할 수 있습니다 didReceiveData)에서 수행하고, 그렇다면 필요한 모든 정리 작업을 수행 한 다음 작업을 완료하십시오 (위의 completeOperation 메서드).당신은 당신이 정기적으로 취소 상태를 확인할 수있는 장소가없는 경우

    • , 당신은 당신이 필요로하는 어떤 정리하지 [super cancel]를 호출하는 cancel 메소드를 오버라이드 (override) 할뿐만 아니라, 너무 작업이 완료 있음 (예를 들어 전화를 보장 작업이 실행중인 경우 completeOperation).

    나는 또한 start 검사에게 취소 상태가 : 위의 너머

    - (void)start 
    { 
        if ([self isCancelled]) { 
         self.finished = YES; 
         return; 
        } 
    
        self.executing = YES; 
    
        // start my operation 
    } 
    

를, 그것은 (당신이 더 작업의 중심에 무엇에 대해 좀 더 알고없이 변호인 어렵다 NSURLConnection? NSURLSession? 다른 것?).

자세한 내용은 동시 실행을위한 작업 구성 (Concurrency Programming Guide: Operation Queues)을 참조하십시오.

관련 문제