2013-01-18 10 views
0

는 내가 API 중 하나에서 다음 코드를 발견, 나는 vm_stat 1의 실시간 모니터링 할 그것을 사용하려고 해요 :왜 waitForDataInBackgroundAndNotify가 두 개 이상의 인수가있는 실시간 모니터에서 작동하지 않습니까?

BOOL terminated = NO; 

-(void)realTimeMonitor 
{ 

NSTask *task = [[NSTask alloc] init]; 
[task setLaunchPath:@"/bin/bash"]; 
[task setArguments:[NSArray arrayWithObjects:@"-c", @"/usr/bin/vm_stat 1", nil]]; //works fine 

// [task setArguments:[NSArray arrayWithObjects:@"-c", @"/usr/bin/vm_stat 1 | /usr/bin/awk '{print $1}'", nil]]; not working 

NSPipe *pipe = [NSPipe pipe]; 
NSPipe *errorPipe = [NSPipe pipe]; 
[task setStandardOutput:pipe]; 
[task setStandardError:errorPipe]; 

NSFileHandle *outFile = [pipe fileHandleForReading]; 
NSFileHandle *errFile = [errorPipe fileHandleForReading]; 


[task launch]; 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(terminated:) 
              name:NSTaskDidTerminateNotification 
              object:task]; 

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(outData:) 
              name:NSFileHandleDataAvailableNotification 
              object:outFile]; 

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(errData:) 
              name:NSFileHandleDataAvailableNotification 
              object:errFile]; 


[outFile waitForDataInBackgroundAndNotify]; 
[errFile waitForDataInBackgroundAndNotify]; 
while(!terminated) 
{ 
    if (![[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) 
    { 
     break; 
    } 
} 
} 

-(void) outData: (NSNotification *) notification 
{ 
NSFileHandle *fileHandle = (NSFileHandle*) [notification object]; 
NSData *data = [fileHandle availableData]; 

if ([data length]) { 

    NSString *currentString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
    // do something 
} 

[fileHandle waitForDataInBackgroundAndNotify]; //Checks to see if data is available in a background thread. 
} 


-(void) errData: (NSNotification *) notification 
{ 
NSLog(@"errData"); 
NSFileHandle *fileHandle = (NSFileHandle*) [notification object]; 
[fileHandle waitForDataInBackgroundAndNotify]; 
} 

- (void) terminated: (NSNotification *)notification 
{ 
NSLog(@"Task terminated"); 
[[NSNotificationCenter defaultCenter] removeObserver:self]; 
terminated =YES; 
} 

========을

setArguments 행을 살펴보십시오. 첫 번째 것은 "/ usr/bin/vm_stat 1"을 완벽하게 작동하지만 두 번째 줄은 "/ usr/bin/vm_stat 1 |/usr/bin/awk '{print $ 1}'" 모두),하지만 터미널에서 실행하면 완벽하게 작동합니다. 그게 왜?

답변

0

awk은 stdout 스트림을 tty 장치에 쓰지 않는다고 생각하기 때문에 stdout 스트림을 버퍼링 할 수 있습니다.

awk의 표준 입력이 가득하고 awk에는 소비자가없는 도착의 표준 출력이 경우는 표준 출력에 기록 vm_stat 불가능이 될 수 있기 때문에이 결국 완전한 교착 상태가 발생할 수 있습니다.

그러므로 fflush() 기능을 사용하여 awk의 stdout을 내뿜어보십시오.

[task setArguments:[NSArray arrayWithObjects:@"-c", @"/usr/bin/vm_stat 1 | /usr/bin/awk '{print $1; fflush();}'", nil]]; 

나는 (약간 수정)를 사용하여 코드 asynctask.m를 실행 할 수 있었다.