1

다른 스레드에서 차단 작업을 가장 잘 취소하는 방법은 훨씬 일반적인 질문 일 수 있지만 Grand Central Dispatch 컨텍스트의 솔루션에 관심이 있습니다. 네트워크에서 데이터를 얻을 때까지 기본적으로 차단하는 함수를 호출해야합니다. 잠재적으로 영원히 차단 될 수 있습니다. 나는이 차단 된 호출이 개인 디스패치 대기열에서 발생하도록 데이터를 가져 오면 메인 대기열에 다시 블록을 넣도록 설정했습니다. 문제는 일단 개인 큐 블록을 차단하고 호출을 차단하면 결코 취소 할 수 없다는 것입니다. 이 기능이 사용자 설정 토글과 연결되어 있다고 가정 해보십시오. 그들이 토글 오프했다면, 나는이 차단 작업과 실행 블록이 본질적으로 끝나기를 바랄 것이다. 이 유형의 문제에 대한 좋은 해결책이 있습니까?다른 디스패치 대기열에서 블록을 취소하는 패턴이 있습니까?

감사

당신은 할 수 없습니다
- (void)_beginListeningForNetworkJunk 
{ 
    dispatch_async(my_private_queue, ^{ 
     // blocks until it gets data 
     id data = [NetworkListener waitForData]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self _handleNetworkData:data]; 
     }); 
    }); 
} 

- (void)_endListeningForNetworkJunk 
{ 
    // How do I kill that job that is blocked on my private queue? 
} 

답변

1

. 문제는 블로킹 및 인터럽트 불가능 인터페이스에서 NetworkListener입니다.

일반적으로 블록을 비동기 적으로 네트워크 연결을 처리하도록 코딩하고 사용자 지정 실행 루프 소스 (또는 NSPort 또는 파이프 파일 설명자 등)와 같은 다른 신호 메커니즘을 모니터링합니다. 네트워크 연결이 작동하면 서비스가 제공됩니다. 신호 메커니즘이 시작되면 네트워크 연결을 종료하고 블록을 종료합니다.

이렇게하면 블록을 협력하여 취소 할 수 있습니다.

블록이 -waitForData에 붙어 있으므로 협조 할 수 없습니다. 협력없이 블록을 취소 할 수있는 메커니즘은 없습니다. NSOperation과 NSThread도 마찬가지입니다. 그 이유는 기본적으로 협력없이 다른 스레드의 활동을 종료하는 것이 불가능하기 때문입니다.

네트워킹 코드에 대해 다른 디자인이 필요합니다.

+0

Darn. 내가 사용중인 API는 내 것이 아닙니다. 그 프레임 워크. –

+0

공개적으로 액세스 할 수있는 프레임 워크입니까 (예 : 오픈 소스)? –

0

원칙적으로 다른 스레드에서 실행중인 내용은 취소 할 수 없습니다. 다른 스레드에서 실행중인 작업을 취소하도록 정중하게 요청할 수 있습니다. 나는 보통 "cancel"이 객체에서 호출 될 수 있도록 태스크를 나타내는 객체를 생성한다.

상황에 따라 : waitForData는 취소 할 수 없습니다 (NetworkListener에 API가 없으면 waitForData에서 데이터 도착과 취소를 구별하는 메커니즘이 필요함).

_endListenForNetworkJunk에서 BALL 값을 "cancelled"로 설정하여 통화가 취소되었음을 나타낼 수 있습니다. 그런 다음 기본 대기열에서 실행되는 코드에서 해당 "취소됨"값이 여전히 지워져 있는지 확인하십시오. 그렇게하면 주 스레드에서 _endListenForNetworkJunk를 호출하면 _handleNetworkData가 호출되지 않는다는 것을 확신 할 수 있습니다. 다른 스레드에서 _endListenForNetworkJunk를 호출하면 주 스레드가 _handleNetworkData에 대한 호출을 시작했을 수 있습니다.

주 대기열에 발송하기 바로 전에 "취소됨"을 선택한 경우 해당 블록은 주 스레드에서 _endListenForNetworkJunk를 호출하기 직전에 이미 전달되지만 실행되지 않을 수 있습니다.

관련 문제