2013-04-08 20 views
7

Tôi đang cố gắng đọc dữ liệu từ Lỗi chuẩn của số NSTask trong ca cao sử dụng waitForDataInBackgroundAndNotify. Đoạn mã sau đọc luồng, vì vậy nó đã hoạt động một phần.NSFileHandleDataAvailableNotification tệp liên tục mà không có dữ liệu mới (dẫn đến việc sử dụng CPU rất cao)

Vấn đề tôi gặp phải là đôi khi NSFileHandleDataAvailableNotification bắt đầu kích hoạt liên tục (hàng nghìn lần mỗi giây) mà không có dữ liệu mới nào cả ([data length] trả về 0). Quá trình của tôi sau đó bắt đầu sử dụng rất nhiều CPU, làm chậm máy. Có ai trong số các bạn đánh một cái gì đó như thế này trước đây trong quá khứ không? Cảm ơn trước.

/** 
* 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]; 
} 

Trả lời

9

Vì vậy, hãy tự mình tìm ra. Theo số NSFileHandle Class Reference, nếu đối tượng NSData được trả lại bởi availableData có độ dài 0, điều đó có nghĩa là đã kết thúc tệp. Tôi đã không xử lý trường hợp này một cách chính xác. Điều này đã khắc phục sự cố cho tôi:

/** 
* 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]; 
    } 
} 
+0

Bạn cũng nên đóng tệp. –

+4

Tôi thích cách hư không trong tài liệu được đề cập rằng 'waitForDataInBackgroundAndNotify' phải được gọi lại sau khi thông báo đến. Cảm ơn! –

Các vấn đề liên quan