If I have a background thread doing some network stuff, and some of the background methods make 'performSelectorOnMainThread' calls, will/can these calls interrupt execution of the current code block (which is being executed on the main thread)?
No, they will and can not. The performSelector group of methods schedule actions on the run loop. Only after your current code block returns to the run loop, these actions will be performed. (Assuming with "the current code block" you mean your code running on the main thread)
If waitUntilDone is set to YES, then absolutely it will definitely interrupt execution of the code calling performSelectorOnMainThread. If it's set to NO then it will queue the selector to be performed on the main thread.
If the caller of performSelectorOnMainThread is not the main thread, then whether or not the selector gets run before your "current code block" finishes will depend entirely upon the state the CPU is in. There might be more than one CPU so you might have 2 of your threads scheduled at the same time, or just the OS might have decided to schedule the main thread instead of your current thread after some time.
So basically, yes, these calls can interrupt execution of the current code block, just in the same way as you should be familiar with from multi-threaded programming.
[By "current code block" I am assuming you mean the caller of performSelectorOnMainThread]
Update:
Ah, right, you mean "Can it interrupt the code which is currently being executed on the main thread?". The answer to that, is definitely not. It is scheduled on the main thread's run loop to run next time round the loop.
Related
Lets say, i have a complex calculation running in NSOperation block. I have paused it. Closed the app. Then restarted the app. Can i recover the last state and continue from there?
Is there existing solution for such a problem or it can be only custom built for certain purposes?
The question is a bit vague, so it's hard to say without knowing all of the code in play. With that said, I may approach the problem by:
Option 1. In your subclass of NSOperation, add your own atomic KVO property "isPaused". Within the operation itself, observe that property and handle accordingly if it ever changes.
Option 2. Are you ever suspending the Operation Queue itself? If so, consider observing that property from within your operations, and each one independently can take action if that value changes.
Option 3. Cancel all operations in the queue, and if the view appears again, just restart with new operations.
Overall, though, there is no magic bullet for pausing operations already in progress. You'll have to bake your own solution. The damage shouldn't be too bad though.
Suspending and Resuming Queues If you want to issue a temporary halt to the execution of operations, you can suspend the corresponding operation queue using the setSuspended: method.
Suspending a queue does not cause already executing operations to pause in the middle of their tasks. It simply prevents new operations from being scheduled for execution. You might suspend a queue in response to a user request to pause any ongoing work, because the expectation is that the user might eventually want to resume that work.
For more detail Refer this link apple docs: http://developer.apple.com/library/mac/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html
If I had a block like so:
(void) ^contrivedExample = ^{//some expensive operation//};
And use it like so:
int test = 1;
contrivedExample()
test++;
Since incrementing test takes no time, will this only occur after my block has fully executed?
Yes, they will hold execution. The increment will occur only after your expensive block finishes executing.
If you need to brush up on your blocks, here's a good read on the matter:
https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html
Yes. Incrementing test will occur after the block has completely finished executing. Blocks aren't asynchronous in and of themselves, although they are often used by APIs that are asynchronous.
Yes. You can even have it run on a different thread by calling either dispatch_sync or dispatch_async.
dispatch_sync means the block runs on a different thread, while the current thread waits for the block to complete.
dispatch_async sends the block to another thread and the current thread continues.
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.
I was going through some tutorial on SystemC and there was a mention that we cant put wait in SC_METHOD, it didn't explain why.
That is because SC_METHOD does not have its own thread of execution. Every time an event on an SC_METHOD sensitivity list is triggered, the SC_METHOD's code is (ideally) entirely executed. In other words, calling wait() in an SC_METHOD would freeze the simulation itself.
In contrast, an SC_THREAD has its own thread of execution and its activity is generally modeled inside a loop containing or not wait() statements, which pauses the execution of the thread. Whenever an event (of the sensitivity list) is triggered, the execution is resumed at the command that follows the previously issued wait().
Its a feature of the language. SC_METHOD is meant to executed to completion without being deferred or losing context, unlike SC_THREAD.
Let's assume we have simple UI and for whatever reason, every 5 seconds a UILabel needs to be updated.
I can now either setup an NSTimer which does the job, or create a separate thread which runs endlessly, sleeps 5 seconds, does its thing, sleeps again and so on.
Which one would I choose to go for? What are the differences?
You have to do UI operations on the main thread anyway, so unless your doing some processing prior to setting the label there would be no benefit of using another thread.
The UI can only be updated on the main thread of any program. If you want to do calculations for the label in a separate thread, that's perfectly fine, but the code to update your UI will have to operate on the main thread (or, you can use performSelectorOnMainThread:withObject:waitUntilDone: to call setText: on your label and have it operate correctly).
Use NSTimer.
Why?
As soon as you introduce extra threads, you introduce the possibility of a whole new class of bugs i.e. thread synchronisation issues. These tend to be very hard to diagnose and resolve due to their indeterminate nature.
You have to do UI updates on the main thread anyway. So your thread would have to do -performSelectorOnMainThread:withObject:waitUntilDone: to update the UI.
If the calculations for the label take a while (don't just assume they do, try it the simple way first and see), have your timer kick off an NSOperation to do the calculations and then have the NSOperations call -performSelectorOnMainThread:withObject:waitUntilDone: when it has finished.