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
.
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
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
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.
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