NSTask阻止主线程

时间:2011-11-28 14:04:13

标签: objective-c multithreading cocoa nsthread nstask

从我的主线程中,我使用

调用选择器
[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阻塞主线程(和UI)。但事实并非如此。 如果我删除

[task launch];

主线程不会被阻止。我究竟做错了什么? O_O

(BTW dataReady只处理数据。这不是阻止......的方法。)

编辑:我刚刚发现,我没有从主线程调用选择器。我从一个单独的线程中调用它!不幸的是,我必须从该线程中调用它。

2 个答案:

答案 0 :(得分:3)

我不知道这是否是您问题的答案,但您确实有一个根本问题:

readInBackgroundAndNotify的文档说:

  

您必须从具有活动运行循环的线程调用此方法。

你没有这样做,因为startTask在它自己的线程上并且你没有在它上面运行一个运行循环。

答案 1 :(得分:3)

我不确定问题是什么,但我建议调查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];

Lemme知道您是否有任何问题

在文档中有关于NSOperationQueue的一些信息,如果您想知道:

  

操作队列通常提供用于运行它们的线程   操作。在Mac OS X v10.6及更高版本中,操作队列使用   libdispatch库(也称为Grand Central Dispatch)启动   执行他们的业务。结果,操作总是如此   在一个单独的线程上执行,无论它们是否存在   指定为并发或非并发操作。