2013-09-16 3 views
0

나는 쉘 명령을 실행하고 NSPipe를 통해 데이터를 출력하기 위해 NSTask를 사용한다. 처음에는 출력 데이터를 읽기 위해 벨로우 (bellow) 메서드를 사용했지만 아무런 문제가 없습니다.NSTask : NSPipe에서 읽을 때 프로그램이 차단되는 이유는 무엇입니까?

- (void)outputAvailable:(NSNotification *)aNotification { 
    NSString *newOutput; 
    NSMutableData *allData = [[NSMutableData alloc] init]; 
    NSData *taskData = nil;   
    if((taskData = [readHandle availableData]) && [taskData length]) 
    newOutput = [[NSString alloc] initWithData:allData encoding:NSASCIIStringEncoding]; 
    NSLog(@"%@", newOutput); 
    [readHandle readInBackgroundAndNotify];  
} 

이 방법의 문제점은 4096 바이트 데이터 만 출력한다는 것입니다. 그래서 while 루프를 사용하여 나는이 같은 방법을 수정, 더 많은 데이터를 얻을 수 있습니다 :

다음
- (void)outputAvailable:(NSNotification *)aNotification { 
    NSString *newOutput; 
    NSMutableData *allData; //Added. 
    NSData *taskData = nil; 
    while ((taskData = [readHandle availableData]) && [taskData length]) { 
    [allData appendData:taskData]; 
    }  
    newOutput = [[NSString alloc] initWithData:allData encoding:NSASCIIStringEncoding]; 
    NSLog(@"%@", newOutput); 
    [readHandle readInBackgroundAndNotify]; 
} 

문제가 발생합니다 : 프로그램이 while 루프에 차단하고 다음과 같은 문장을 수행 할 수 없습니다. 나는 allData이 내가 원하는 것임을 보장하지만, 마지막 데이터 청크를 추가 한 후에는 차단하고있다. 몇 가지 해결책을 제공해 주시겠습니까? 감사.

답변

0

귀하의 while() 루프는 사실상 추가 알림을 차단하여 전체 프로그램이 버퍼 플러시를 기다리는 동안 차단되도록합니다.

readInBackgroundAndNotify을 입력 한 다음 각 알림에 availableBytes을 입력하고 NSMutableData (인스턴스 변수에 포함될 가능성이 높음)에 추가하십시오. 알림을 처리 할 때 더 많은 데이터를 기다리거나 어떤 종류의 루프도 실행하지 마십시오. while 더 많은 데이터를 사용할 수있게되면 시스템에서 사용자에게 알립니다.

e.e. 시스템이 데이터를 사용자에게 푸시하면 시스템에서 데이터를 가져 오지 않습니다.


아 ... 확인. 사용 가능한 데이터가있을 때만 데이터를 가져와야합니다. 귀하의 while() 루프가이를 수행하고 있습니다. 커피가 충분하지 않습니다. 내 잘못이야.

외부 프로세스가 파이프를 닫지 않기 때문에 마지막 블록이 가장 가능성이 높습니다. EOF는 수신되지 않으므로 프로그램은 절대 도착하지 않는 더 많은 데이터를 영원히 기다리고 있습니다.

다음 중 하나를

  • 당신이 어떤 종류의 일을하는 경우 백그라운드 작업 프로세스

을 충분한 데이터를받은 때를 감지 및 종료

  • 을 종료해야합니다 프로세스 표준 입력에 데이터를 쓰는 변환 프로그램 (예 : tr)을 사용하면 표준 입력 파이프를 닫아야합니다.

  • +0

    정말 이해가 가지 않습니다. 죄송합니다. 코드를 보여줄 수 있습니까? 고맙습니다. –

    +0

    'while'루프는 추가 알림을 보내줍니다. 그러나 while 루프는 청크에 의해 모든 데이터 청크를받습니다. 즉, 데이터는 while 루프에 의해 완전히 수신됩니다. 블로킹은 마지막 청크 데이터 (<4096 바이트)를 수신 한 후에 만 ​​발생합니다. –

    +0

    @bbbum, 도와 주셔서 감사합니다. 이제 그 이유를 알았어. 안타깝게도 내 앱이 쉘과 상호 작용하기를 원하기 때문에 백그라운드 작업을 종료 할 수 없습니다 (예 : sh를 실행하고 파이프를 통해 명령을 입력). 두 번째 방법은 데이터 볼륨을 감지 할시기와 방법을 알지 못합니다. 문제의 해결책에 대해 이야기 한 [예제] (http://dev.notoptimal.net/2007/04/nstasks-nspipes-and-deadlocks-when.html)를 찾았지만, 그것은 나에게 유효하지 않습니다. 네 도움이 더 필요해. 다시 한번 감사드립니다. –

    관련 문제