从我的主线程中,我使用
调用选择器[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只处理数据。这不是阻止......的方法。)
编辑:我刚刚发现,我没有从主线程调用选择器。我从一个单独的线程中调用它!不幸的是,我必须从该线程中调用它。
答案 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)启动 执行他们的业务。结果,操作总是如此 在一个单独的线程上执行,无论它们是否存在 指定为并发或非并发操作。