重复使用NSFileHandleDataAvailableNotification文件,没有新数据(导致CPU使用率非常高)

Mar*_*lio 8 cocoa asynchronous objective-c nstask nsfilehandle

我正在尝试NSTask使用Cocoa中的标准错误读取数据waitForDataInBackgroundAndNotify.以下代码确实读取了流,因此它已经部分工作了.

我遇到的问题是,有时NSFileHandleDataAvailableNotification开始重复启动(每秒数千次),根本没有新数据([data length]返回0).然后我的进程开始使用大量CPU,使机器停止运转.你们中的任何人过去曾经打过这样的事吗?提前致谢.

/**
 * Start reading from STDERR
 *
 * @private
 */

- (void)startReadingStandardError {
    NSFileHandle *fileHandle = [_task.standardError fileHandleForReading];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(errorData:)
                                                 name:NSFileHandleDataAvailableNotification
                                               object:fileHandle];
    [fileHandle waitForDataInBackgroundAndNotify];
}

/**
 * Fired whenever new data becomes available on STDERR
 *
 * @private
 */

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

    if ([data length]) {
       // consume data
    }

   [fileHandle waitForDataInBackgroundAndNotify];
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*lio 10

所以,最后我自己搞清楚了.根据NSFileHandle类引用,如果NSData返回的对象availableData的长度为0,则表示已到达文件结尾.我没有正确处理这个案子.这为我修好了:

/**
 * Fired whenever new data becomes available on STDERR
 *
 * @private
 */

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

    if ([data length]) {
        // consume data
        // ...

        [fileHandle waitForDataInBackgroundAndNotify];
    } else {
        // EOF was hit, remove observer
        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleDataAvailableNotification object:fileHandle];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢在文档中没有提到在通知到达后必须再次调用`waitForDataInBackgroundAndNotify`.谢谢! (5认同)