7

我正在尝试使用 NSTask 运行一个简单的 bash 脚本并将输出定向到文本视图。执行任务后,我的应用程序的 CPU 使用率为 100%,即使它很简单echo(目前)。

我创建了一个全新的项目来隔离问题:

@interface AppDelegate ()
@property (nonatomic) NSTask *task;
@property (nonatomic) NSPipe *pipe;
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    self.pipe = [NSPipe pipe];
    self.pipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle *h) {
        NSLog(@"Read: %@", [h readDataToEndOfFile]);
    };

    self.task = [[NSTask alloc] init];
    self.task.launchPath = @"/bin/bash";
    self.task.arguments = @[@"-c", @"echo test"];
    self.task.standardOutput = self.pipe;
    [self.task launch];
}
@end

它被正确执行并且输出(作为一个NSData)被记录为NSLog

PipeTest[3933:2623] Read: <74657374 0a>

但是,在我终止我的应用程序之前,CPU 使用率保持在 100%。

编辑:

Time Profiler 测试返回下面的列表,但我不确定如何解释。

在此处输入图像描述

4

2 回答 2

11

文件句柄保持打开状态?

@interface AppDelegate ()
@property (nonatomic) NSTask *task;
@property (nonatomic) NSPipe *pipe;
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    self.pipe = [NSPipe pipe];
    self.pipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle *h) {
        NSLog(@"Read: %@", [h readDataToEndOfFile]);
        [h closeFile];
    };

    self.task = [[NSTask alloc] init];
    self.task.launchPath = @"/bin/bash";
    self.task.arguments = @[@"-c", @"echo test"];
    self.task.standardOutput = self.pipe;
    [self.task launch];
}

关闭文件NSFileHandle h似乎会使您的 CPU 使用率恢复正常。

于 2012-12-06T17:09:47.487 回答
2

如果应用程序写入的内容超过 NSFileHandle 的实现缓冲区(我在 El Capitan 上观察到的 4K),则建议的代码将不起作用。[h readDataToEndOfFile] 倾向于一次读取 4K,因此此示例可能会过早关闭缓冲区。对于您的处理程序,一种更强大且同样未记录的方法是:

NSData *data = [h readDataToEndOfFile];
if (data.length) {
  NSLog(@"Read: %@", data);
} else {
  [h closeFile];
}
于 2015-11-04T02:11:55.987 回答