2012-12-06 12 views
7

Sto provando a eseguire un semplice script di bash utilizzando NSTask e indirizzare l'output a una visualizzazione di testo. Una volta eseguita l'attività, l'utilizzo della CPU della mia app è al 100%, anche se è un semplice echo (per ora).Utilizzo di NSTask e NSPipe causa l'utilizzo della CPU al 100%

ho creato un progetto completamente nuovo per isolare il problema:

@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 

E viene eseguito correttamente e l'uscita (come NSData) viene registrato con NSLog:

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

Tuttavia l'utilizzo della CPU rimane al 100% fino a quando non chiudo la mia app.

EDIT:

test A Tempo Profiler restituisce la lista qui sotto, ma non sono sicuro come interpretare questo.

enter image description here

risposta

9

maniglia File lasciata aperta?

@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]; 
} 

chiusura del file sul NSFileHandleh sembra tornare l'utilizzo della CPU alla normalità.

+1

Questo è fantastico, grazie! Puoi anche spiegare * perché * la CPU reagisce in questo modo agli handle di file aperti lasciati? –

2

Il codice suggerito non funzionerebbe se l'app scrive più del buffer di implementazione di NSFileHandle (4K nella mia osservazione su El Capitan). [h readDataToEndOfFile] tende a leggere 4K alla volta, quindi questo esempio potrebbe chiudere il buffer prematuramente. Un approccio più robusto e altrettanto priva di documenti per il gestore è questo:

NSData *data = [h readDataToEndOfFile]; 
if (data.length) { 
    NSLog(@"Read: %@", data); 
} else { 
    [h closeFile]; 
}