【问题标题】:why waitForDataInBackgroundAndNotify doesn't work with the real time monitor with more than 1 argument?为什么 waitForDataInBackgroundAndNotify 不能与超过 1 个参数的实时监视器一起使用?
【发布时间】:2013-01-18 22:08:35
【问题描述】:

我从其中一个 API 中找到了以下代码,我正在尝试使用它来实时监控 vm_stat 1:

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}'”(没有输出全部),但如果我在终端上运行它,它工作得非常好。这是为什么呢?

【问题讨论】:

    标签: objective-c nstask nspipe


    【解决方案1】:

    也许awk 正在缓冲其标准输出流,因为它认为它没有将其标准输出流写入 tty 设备。

    这最终可能导致完全死锁,因为如果awk 的标准输入已满且awk 的标准输出上没有消费者,vm_stat 可能无法写入其标准输出。

    因此尝试使用其内置的fflush() 函数刷新awk 的标准输出。

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

    我能够使用(稍作修改)asynctask.m 运行您的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-28
      • 2020-05-28
      • 2011-06-04
      • 2017-09-21
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多