NSTask:为什么程序在从NSPipe读取时会阻塞?

时间:2013-09-16 15:19:51

标签: objective-c blocking nstask nspipe

我使用NSTask运行shell命令并通过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是我想要的,但在追加最后一个数据块之后,它就是阻塞的。 你能给我一些解决方案吗?感谢。

1 个答案:

答案 0 :(得分:0)

你的while()循环有效阻止了进一步的通知,导致整个程序阻塞等待刷新缓冲区的东西。

您应该readInBackgroundAndNotify,然后在每个通知上取消availableBytes,将其附加到您的NSMutableData(可能存在于实例变量中)。处理通知时,请勿尝试等待更多数据或执行任何类型的while循环。当有更多数据可用时,系统会通知您。

即。系统会将数据推送给您,您不会从系统中提取数据。


啊,好吧。您应该仍然只在有可用数据时提取数据。你的while()循环正在这样做。咖啡不够。我的坏。

最后一个块很可能是因为你的外部进程没有关闭管道;没有收到EOF,因此,程序正在等待永远到达的更多数据。

或者:

  • 确保后台任务退出

  • 检测您何时收到足够数据并终止流程

如果您正在进行某种转换程序(例如,tr),您在其中编写有关进程标准输入的数据,则可能需要关闭标准输入管道。