Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If performSelectorOnMainThread:waitUntilDone: is called from the main thread, when will it execute?

I'm programming an application that makes use of asynchronous web requests using NSURLConnection, so I have multiple threads running. To ensure that the main logic of my app happens on one thread, I am making heavy use of performSelectorOnMainThread:waitUntilDone:. Sometimes though, I am running this on the main thread, which piqued my curiosity.

If performSelectorOnMainThread:waitUntilDone: is called while in the main thread? Does it act the same as just performSelector:? What if waitUntilDone: is YES? What if it is NO?

EDIT: I have found that when waitUntilDone: is YES, the selector is executed (almost) immediately, but I cannot figure out when it is executed if waitUntilDone: is NO.

like image 516
Jumhyn Avatar asked Jul 11 '13 23:07

Jumhyn


3 Answers

performSelectorOnMainThread:withObject:waitUntilDone:

is a method to deliver message on main thread of your application. Here boolean value in parameter waitUntilDone: specifies that whether you want to block your main thread to execute specified selector or not.

for example -

if you written these two lines-

[self performSelectorOnMainThread:@selector(print) withObject:nil waitUntilDone:YES];

NSLog(@"Hello iPhone");

and this is the print method -

- (void) print
{
    NSLog(@"Hello World");
}

then you will get this o/p

Hello World
Hello iPhone

so it first pause the execution of your main thread and print "Hello World" and then execute main thread again and print "Hello iPhone" because you specified YES in waitUntilDone:

but if you specified NO in waitUntilDone: then it will print like this -

Hello iPhone
Hello World

it clearly indicates that it put your request of executing the specified selector in a queue and as OS gets its main thread free it executed you request.

Calling performSelectorOnMainThread:withObject:waitUntilDone: either from main thread or a secondary thread doesn't make any difference in it's execution, it depends on what you specified in waitUntilDone:

for more info -

NSObject Class Reference

like image 21
saadnib Avatar answered Nov 07 '22 14:11

saadnib


If the current thread is also the main thread, and you pass YES,
the message is performed immediately, otherwise the perform is
queued to run the next time through the run loop.

If YES, it can be performed before performSelectorOnMainThread:withObject:waitUntilDone: returns.

I have found that when waitUntilDone: is YES, the selector is executed (almost) immediately, but I cannot figure out when it is executed if waitUntilDone: is NO.

The bit about the run loop: Your main thread has a run loop. This more or less prevents a thread from exiting. A run loop manages a todo list. When its work is complete, it suspends execution of that thread for some time. Then it wakes up later and sees if has work to do.

The amount of work can vary greatly (e.g. it may do some really heavy drawing or file i/o between the time it awakes and the point your selector is performed. Therefore, it's not a good tool for really precise timing, but it should be enough to know how it works and how the implementations adds the work to the run loop.

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

like image 111
justin Avatar answered Nov 07 '22 14:11

justin


If waitUntilDone: is YES it acts as an immediate function call.

If waitUntilDone: is NO then it queues the call along with all other threads' calls.

This method queues the message on the run loop of the main thread using the common run loop modes—that is, the modes associated with the NSRunLoopCommonModes constant. As part of its normal run loop processing, the main thread dequeues the message (assuming it is running in one of the common run loop modes) and invokes the desired method.

As noted above, things like drawing and I/O are prioritized over anything in queues. Once the main thread gets around to having time for queue service in the next event loop, there's a couple other details that make it not quite as simple as counting on first in first out:

1) dispatch_async() blocks ignore modes.

2) The performSelector variants with a specific mode argument -- event tracking, say -- may take precedence over ones with the default common modes argument in a loop running in that specific mode.

As a general rule, if you want predictable timing behaviours you should use the low level GCD dispatch functions that don't take account of higher level considerations like run loop modes.

like image 1
Alex Curylo Avatar answered Nov 07 '22 14:11

Alex Curylo