Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does performSelectorInBackground and detachNewThreadSelector work?

I need to perform an asynchronous function execution because it is blocking the main thread and hence the UI is not available.

After looking at the questions in stackoverflow, I know there are three ways to do asynchronous function.

An example:

[NSThread detachNewThreadSelector:@selector(showSpinner:) toTarget:self withObject:self.view];
// or 
[self performSelectorInBackground:@selector(showSpinner:) withObject:self.view];
// or 
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(showSpinner:) object:self.view];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];
// or 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self showSpinner:self.view];
    });
});

My question is how does performSelectorInBackground and detachNewThreadSelector return back to main thread? how do you know that they are done?

like image 329
lakshmen Avatar asked Mar 13 '13 03:03

lakshmen


2 Answers

A couple of thoughts:

  1. You might want to check Migrating Away From Threads in the Concurrency Programming Guide, which makes a compelling argument for dispatch queues and operation queues, which are discussed earlier in that same guide.

  2. Also, as you delve into various asynchronous operations, remember, do time consuming stuff in background queues/threads, but always dispatch UI stuff back to the main queue. I only mention that because your task, showSpinner sounds a lot like a UI task, which you would never want to do in a background queue/thread. If it has some "expensive" non-UI related tasks, then fine, do that in the background, but make sure the UI stuff gets dispatched back to the main queue.

  3. There are, as an aside, other renditions of the operations queues, e.g., block operations:

    NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
    [opQueue addOperationWithBlock:^{
        // do some slow stuff in the background here
    
        // ok, now do UI stuff in the main queue
    
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self showSpinner:self.view];
        }];
    }];
    

    This is roughly equivalent to the GCD (dispatch queue) rendition:

    dispatch_queue_t dispatchQueue = dispatch_queue_create("com.ramshad.app", 0);
    dispatch_async(dispatchQueue, ^{
        // do some slow stuff in the background here
    
        // ok, now do UI stuff in the main queue
    
        dispatch_async(dispatch_get_main_queue(), ^{
            [self showSpinner:self.view];
        });
    });
    

    There are tons of subtle pros and cons between the operation queues and dispatch queues (which we should not get into here because it's been discussed hundreds of times elsewhere on Stack Overflow), but both let you do surprisingly rich asynchronous operations with less complexity than traditional thread programming.

  4. If you decide to stick with threads versus operation and/or dispatch queues (which I wouldn't necessarily recommend), you might want to check out the Threading Programming Guide.

like image 115
Rob Avatar answered Nov 15 '22 09:11

Rob


To identify performSelectorInBackground & detachNewThreadSelector end of execution,call a method at the end of the thread method on main thread.

Additionaly NSThread provides an propery as isFinished which returns a Boolean value that indicates whether the receiver has finished execution.

Example:

[self performSelectorOnMainThread:@selector(threadMethod) 
                       withObject:nil 
                    waitUntilDone:NO];

or

[NSThread detachNewThreadSelector:@selector(threadMethod) 
                         toTarget:self 
                       withObject:nil];

-(void)threadMethod{

    //here your implementation code
    //here call the end notification method.
    [self performSelectorOnMainThread:@selector(ThreadExecutionDone) 
                           withObject:nil 
                        waitUntilDone:YES];
}

-(void)ThreadExecutionDone{
    //end of the performSelectorInBackground or detachNewThreadSelector.
}
like image 30
Shamsudheen TK Avatar answered Nov 15 '22 10:11

Shamsudheen TK