From my main thread I call a selector using
[self performSelectorInBackground:@selector(startTask) withObject:nil];
This is the method 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];
}
This should prevent NSTask from blocking the main thread (and the UI). But it doesn't. If I remove
[task launch];
The main thread doesn't get blocked. What am I doing wrong? o_O
(BTW dataReady just handles the data. It's not this method, that blocks...)
EDIT: I just found out, that I am not calling the selector from the main thread. I call it from a separate thread! Unfortunately I have to call it from that thread.
I don't know if this is the answer to your question, but you do have a fundamental issue:
The docs for readInBackgroundAndNotify say:
You must call this method from a thread that has an active run loop.
You are not doing that because startTask is on its own thread and you are not running a run loop on it.
I'm not sure what the issue is but I suggest looking into 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 know if you have any questions
In the documentation heres some info on NSOperationQueue just if you were wondering:
Operation queues usually provide the threads used to run their operations. In Mac OS X v10.6 and later, operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations. As a result, operations are always executed on a separate thread, regardless of whether they are designated as concurrent or non-concurrent operations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With