NSTask блокирует основной поток - PullRequest
3 голосов
/ 28 ноября 2011

Из основного потока я вызываю селектор, используя

[self performSelectorInBackground:@selector(startTask) withObject:nil];

Это метод startTask:

-(void)startTask{    
   NSTask *task = [[NSTask alloc] init];
   NSPipe *pipe = [[NSPipe alloc] init];
   NSFileHandle *fh = [pipe fileHandleForReading];

   NSArray *args = [NSArray arrayWithObjects:@"-z",iPAddress, [NSString stringWithFormat:@"%@",portNumber], nil];

   [task setLaunchPath:@"/usr/bin/nc"];
   [task setArguments:args];
   [task setStandardOutput:pipe];

   NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
   [nc removeObserver:self];
   [nc addObserver:self
          selector:@selector(dataReady:)
              name:NSFileHandleReadCompletionNotification
            object:fh];

   [task launch];
   [fh readInBackgroundAndNotify];
}

Это должно предотвратить блокировку NSTask основного потока (и пользовательского интерфейса),Но это не так.Если я удаляю

[task launch];

Основной поток не блокируется.Что я делаю неправильно?o_O

(Кстати, dataReady просто обрабатывает данные. Блокирует не этот метод ...)

РЕДАКТИРОВАТЬ: Я только что узнал, что я не звонюселектор из основного потока.Я называю это из отдельной ветки!К сожалению, я должен назвать это из этой темы.

Ответы [ 2 ]

3 голосов
/ 28 ноября 2011

Я не уверен, в чем проблема, но я предлагаю изучить NSOperationQueue.

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^(void) {
   NSTask *task = [[NSTask alloc] init];
   NSPipe *pipe = [[NSPipe alloc] init];
   NSFileHandle *fh = [pipe fileHandleForReading];

   NSArray *args = [NSArray arrayWithObjects:@"-z",iPAddress, [NSString stringWithFormat:@"%@",portNumber], nil];

   [task setLaunchPath:@"/usr/bin/nc"];
   [task setArguments:args];
   [task setStandardOutput:pipe];

   NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
   [nc removeObserver:self];
   [nc addObserver:self
          selector:@selector(dataReady:)
              name:NSFileHandleReadCompletionNotification
            object:fh];

   [task launch];
}];
[queue autorelease];

Позвольте мне знать, если у вас есть какие-либо вопросы

В документации есть некоторая информация о NSOperationQueue просто, если вам интересно:

Очереди операций обычно предоставляют потоки, используемые для выполнения их операций.В Mac OS X 10.6 и более поздних версиях очереди операций используют библиотеку libdispatch (также известную как Grand Central Dispatch), чтобы инициировать выполнение своих операций.В результате операции всегда выполняются в отдельном потоке, независимо от того, обозначены ли они как одновременные или не параллельные операции.

3 голосов
/ 28 ноября 2011

Я не знаю, является ли это ответом на ваш вопрос, но у вас есть фундаментальная проблема:

Документы для readInBackgroundAndNotify говорят:

Вы должны вызывать этот метод из потока, который имеет активный цикл выполнения.

Вы не делаете этого, потому что startTask находится в своем собственном потоке, и вы не запускаете цикл выполнения в нем.

...