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 — это то, что я хотел, но после добавления последнего фрагмента данных он блокируется. Не могли бы вы дать мне несколько решений? Спасибо.


person Gate Luma    schedule 16.09.2013    source источник


Ответы (1)


person    schedule
comment
Я действительно не понимаю, извините. Не могли бы вы предоставить какие-либо коды, чтобы продемонстрировать это? Спасибо. - person Gate Luma; 16.09.2013
comment
Вы говорите, что цикл while блокирует дальнейшие уведомления. Но цикл while получает все данные по частям, то есть данные полностью принимаются циклом while. Блокировка происходит только после получения последнего фрагмента данных (‹4096 байт). - person Gate Luma; 16.09.2013
comment
@bbbum, спасибо за помощь. Теперь я знаю, почему. К сожалению, я не могу выйти из фоновой задачи, потому что мое приложение хочет взаимодействовать с оболочкой (например, запустить sh и ввести команду через канал). Что касается второго способа, я не знаю, когда и как определить объем данных. Я нашел пример, в котором говорилось о решение проблемы, но оно мне не подходит. Мне нужна ваша дальнейшая помощь. Еще раз спасибо. - person Gate Luma; 16.09.2013
comment
@GateLuma В каком формате считываются данные? Как правило, в любом заданном протоколе/формате есть какой-то способ узнать, когда все данные были получены. За исключением этого, вам понадобится какой-то сигнальный механизм, который потребует изменения кода любого внешнего инструмента, который вы используете. - person bbum; 16.09.2013
comment
Данные представляют собой результат выполненной команды оболочки, такой как ls или system_profiler. Есть ли простые решения этой проблемы? - person Gate Luma; 17.09.2013