2010-07-21 3 views
1

안에있는 NSTask을 실행하려고 잠시 도망 쳤습니다.왜 자동 복구 된 NSTask가 NSOperation 스레드의 runloop을 무기한 차단합니까?

다음은 very simple app입니다. 문제를 보여주기 위해 함께 사용했습니다. 단추를 클릭하면 NSOperation이 대기합니다. NSRunLoop을 설정하고 NSTask을 호출하는 메소드를 호출합니다. 이 작업은 실제로 간단합니다. 단지 /bin/sleep을 2 초 동안 실행합니다 (정상적으로 작동 할 때 회 전자를 쉽게 볼 수있을만큼).

응용 프로그램이 광고 된 것처럼 작동하지만 TaskPerformer.m의 23 번째 줄을 autorelease으로 변경하면 (미안하지만 직접 연결할 수 없기 때문에 새로운 포스터입니다.) 또는 전체적으로 주석 처리합니다. NSTask 개체), NSOperation의 스레드는 절대로 종료하지 않습니다. 그 주요 runloop 뭔가를 차단하는 것 같습니다.

이제 문제는 두 가지입니다. 우선, 왜 스레드가 차단되고 있는지 이해할 수 없지만,이 애플리케이션의 가비지 수집을 켜면 동일한 동작이 나타납니다. NSTask을 수동으로 릴리스 할 수있는 방법이 없기 때문에 스레드는 무엇을 막론하고 블록합니다.

누군가가 내게 어떤 일이 일어 났는지 말해 줄 수 있다면, 영원히 감사 할 것입니다!

답변

1

나는 여기에서 무슨 일이 일어나고 있는지 알아 냈습니다. [runLoop run]에 전화를 걸어서 루프를 설정하고 무기한 실행하고있었습니다. 그것은 while (!done) 루프로 결코 떨어지지 않았습니다. run을 호출 한 후 더 이상 입력이 없을 때까지 NSRunLoop이 실행됩니다. 나의 NSTaskrelease를 부르는 것은 정확하게이 시나리오를 초래했다. 그래서 (꽤 우연히) 나의 runloop이 종료했다.

해결책은 [runLoop run]을 제거하고 단순히 내 자신의 while 루프를 사용하는 것입니다. 희망이 다른 사람을 도와주세요!

4

게시 한 샘플 프로젝트에 몇 가지 다른 문제점이 있습니다.

[task waitUntilExit]; 
[task launch]; 

waitUntilExit 호출이가 작업을 실행 한 후 를 호출하기위한 것입니다, 간단하게 차단하고 작업이 완료 될 때까지 아무것도하지 않는 것 TaskPerformer.m에서, 당신은. 작업이 끝날 때까지 기다리지 않고 신경 쓰는 것만으로도 출력을 얻는 것이 아니라 launch 다음에 waitUntilExit을 호출 할 수 있고 실행 루프를 망칠 필요가 없습니다.

작업에서 출력을 얻으려면 standardOutput을 가져오고, 기본값으로 NSFileHandle을 반환해야합니다. 그런 다음 readDataOfLength: 또는 readDataToEndOfFile으로 전화를 걸면 둘 다 데이터를 사용할 수있을 때 프로세스의 데이터를 차단하고 반환합니다.

어쨌든 백그라운드 스레드에서이 모든 작업을 수행하게되므로이 메소드가 차단되지만 기본 스레드에서 동일한 작업을 수행하지 않으려합니다. 작업이 완료 될 때까지 사용자. 메인 스레드에서이 작업을 수행 한 경우 NSFileHandlereadInBackgroundAndNotify 및 친구들을 사용하고 싶을 것입니다. 그러나 배경 스레드의 경우, NSRunLoop을 사용하는 것이 실제로 필요하지 않습니다.

+0

지적 해 주셔서 고마워요, 브라이언. 나는 이미 그것을 보았고, 업데이트 된 코드를 Github에 푸시하지 않았을뿐입니다.이제 해결되었습니다. 'NSRunLoop'은 실제 응용 프로그램에서 필요합니다. 왜냐하면'NSTask'의 무리를 시작하는 것 외에도 콜백에 NSRunLoop이 필요한 비동기 NSURLConnection을 사용하기 때문입니다. 흥미로운 점은 'waitUntilExit'에 대한 호출을 제거하면 스레드가 처음에는 종료되지만 이후에는 종료하지 않는다는 것입니다. 뭔가 이상하게 보입니다. – texel