NSTask: почему программа блокируется при чтении из NSPipe?
Я использую NSTask для запуска команды оболочки и вывода данных через NSPipe. Во-первых, я использовал метод ниже для чтения выходных данных, это не проблема.
- (void)outputAvailable:(NSNotification *)aNotification {
NSString *newOutput;
NSMutableData *allData = [[NSMutableData alloc] init];
NSData *taskData = nil;
if((taskData = [readHandle availableData]) && [taskData length])
newOutput = [[NSString alloc] initWithData:allData encoding:NSASCIIStringEncoding];
NSLog(@"%@", newOutput);
[readHandle readInBackgroundAndNotify];
}
Проблема метода заключается в том, что он выводит только 4096 байт данных. Поэтому я использую while
цикл, чтобы получить больше данных, измените метод следующим образом:
- (void)outputAvailable:(NSNotification *)aNotification {
NSString *newOutput;
NSMutableData *allData; //Added.
NSData *taskData = nil;
while ((taskData = [readHandle availableData]) && [taskData length]) {
[allData appendData:taskData];
}
newOutput = [[NSString alloc] initWithData:allData encoding:NSASCIIStringEncoding];
NSLog(@"%@", newOutput);
[readHandle readInBackgroundAndNotify];
}
Тогда возникает проблема: программа блокируется в while
цикл и не может выполнять следующие заявления. Я гарантирую, что allData
это то, что я хотел, но после добавления последнего блока данных, он блокируется. Не могли бы вы дать мне несколько решений? Благодарю.
1 ответ
Ваш while()
Цикл эффективно блокирует дальнейшие уведомления, заставляя всю программу блокировать ожидание чего-либо, чтобы очистить буфер.
Вам следует readInBackgroundAndNotify
, а затем снять availableBytes
в каждом уведомлении, добавив его в свой NSMutableData
(который, вероятно, содержится в переменной экземпляра). Когда вы обрабатываете уведомление, не пытайтесь ждать больше данных или делать какие-либо while
петля. Система уведомит вас, когда появится больше данных.
Т.е. система отправляет вам данные, вы не извлекаете данные из системы.
А, ну ладно. Вы все равно должны извлекать данные только при наличии доступных данных. Ваш while()
цикл делает это. Не хватает кофе. Виноват.
Последний блок наиболее вероятен, потому что ваш внешний процесс не закрывает канал; EOF не получен, и, таким образом, программа всегда ожидает большего количества данных, которые никогда не поступают.
Или:
убедитесь, что фоновая задача завершена
определить, когда вы получили достаточно данных, и прекратить процесс
Если вы делаете какую-то программу преобразования (скажем, tr
) где вы записываете данные на стандартный ввод процессов, тогда вам может потребоваться закрыть стандартный канал ввода.