Pausing particular thread in iOS? - ios

in my iPhone app, I have used 2 threads. Both functions differently in different class. On particular condition I want to pause particular thread so I have used
[NSThread sleepForTimeInterval:]
So my question is am I doing right or this sleep causes sleep in whole application? If yes what is other alternative?

If you want to pause your thread for a given amount of time, then [NSThread sleepForTimeInterval:] is just fine. However if you want to wait for a given event to occur (e.g. wait for another thread to catch up) you should take a look at the NSCondition class.

Yeah this is absolutely right. This will pause the current thread on which you are calling [NSThread sleepForTimeInterval:]

Related

What is the best way to ensure the main thread is blocked while a background thread is processing?

Consider the following case:
Main Thread -----UIView info \ --------------------------------------- / Button Updated ------
\ (Some Event) / (Some Event)
\ /
BG Thread ---------------------Validate UIView info-----Update Button------------------------
On the main thread, a UIView is present
UIView makes a dispatch call is made to a background thread
In the BG Thread, the UIView's info is validated.
BG Thread makes a dispatch call to a UIButton on the main thread to update it.
My question is - notice how there is a gap between UIView info and the UIButton which means that the app could technically be updated during this time. How can I possible stop this gap? Essentially, from the BG thread, block the Main Thread till the call comes back?
You cannot and must never block the main thread. If you do, the interface will freeze and, if the blockage lasts too long, the WatchDog process will kill your app dead before the user's very eyes.
You can give the user a sense that something is going on, and discourage the user from doing anything, by, say, turning off user interaction and putting up a spinner. But in general, yes, multithreading is hard; you must be prepared for the possibility that you will come back onto the main thread when the app has changed state.
Rather than block a main thread, disable user input controls in your view until the validation is complete, then re-enable them.
It would also make sense to add an activity indicator with hidesWhenStopped set to true; it will show the user that there's background work in progress if you start it when the background work starts, and stop it when validation is complete.
If there's ever a chance the background process could hang or take longer, e.g. if it's making a network request, you might show/enable a cancel button and a way to terminate it.
Showing activity indicator and possibly providing a cancel button both require that the main thread keep running, so definitely don't block it!
Your button should not be updated in the background. You should always modify UIKit components on the main thread.
You should also never block the main thread, what you're looking for is the show the user an indication that a background process is active. 'UIActivityIndicatorView' might be a good thing to show the user, you could also disable user interaction on the view to prevent the user from touching anything if it's critical for them to wait until the operation is complete but not recommended.
Yes, you should never block the main thread and update UI only on main thread.
That said - show a spinner / activity indicator while busy on the background.
Think carefully about the UI and e.g. present something so the user can not change something while you are busy with e.g. dialog or popover or something like that.
In practise this often becomes more a question of UX than blocking.

Pause Main thread until background thread retrieves user input

In my main starting thread I need to pause the code and start a new thread and wait until I get user input. Then Id like to discard the new thread made and go back to where the main thread left off. But whats happening is that the new thread is called but the main thread keeps going with the code. How do I deal with this without interfering with the user being able to use the interface buttons? I think that maybe another nscondition needs to be made in my if(moveCount == 2) statement? Or that my main thread needs to wait for a signal from my other thread notifying user input is received.
ADDITIONAL NOTE: I would also like the original thread paused in such a way that I can still use my 2 UIButtons in my interface.
MORE ADDITIONAL NOTES AS TO THE QUESTIONS IM RECEIVING: This is a game I'm making. Somewhere mid code means in my main thread in one of my methods. This method decides which direction I'm moving in then i get a tag difference, then make an attack. But sometimes 2 attacks can be made so its at this point the user has 2 buttons to click on the screen to decide which attack to make.
Also its quiet clear to me that I should not pause the main thread now. If so what is the alternative? Thanks
NSCondition and NSThread
#property (strong, nonatomic) NSCondition *condition;
#property (strong, nonatomic) NSThread *aThread;
In my viewDidLoad create the following.
// create the NSCondition instance
self.condition = [[NSCondition alloc]init];
// create the thread
self.aThread = [[NSThread alloc] initWithTarget:self selector:#selector(threadLoop) object:nil];
somewhere mid code..
if(moveCount == 2){
[self.aThread start];
}
// I need to get captureDecision from user from 2 buttons before continue.. How do I pause this thread when aThread is started. Then when capture decision is received discard aThread and start here.
NSLog(#"Capture Decision = %d", captureDecision);
if(captureDecision == 1){
tagDifference = newButton.tag - currentButton.tag;
}else{
tagDifference = currentButton.tag - newButton.tag;
}
}
aThread Method
-(void)threadLoop{
NSLog(#"Thread Loop Triggered");
while([[NSThread currentThread] isCancelled] == NO)
{
[self.condition lock];
while(captureDecision == 0)
{
[self.condition wait];
}
[self.condition unlock];
}
[NSThread exit]; //exit this thread when user input is received
}
What you are requesting is not possible, the main thread IS the one that handles user interactions, whenever you "halt" the main thread the interface becomes unresponsive.
Based on apple's documentation:
The main run loop of your app is responsible for processing all
user-related events. The UIApplication object sets up the main run
loop at launch time and uses it to process events and handle updates
to view-based interfaces. As the name suggests, the main run loop
executes on the app’s main thread. This behavior ensures that
user-related events are processed serially in the order in which they
were received.
Which means that if you halt the main thread you won't be able to.
https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW14
(Unless there is some strange way to make a background thread handle the user interactions which i might not be aware of, but still its pretty strange)
As others have told you here, your approach is far from optimal. Questions you have to ask yourself are, in what part of the code do you want to wait for a certain event to occur, and for what purpose.
If you give us a more detailed explanation of what you want to achieve then we can offer you a much better solution.
EDIT:
What kind of game is it? turn based? something that gets drawn constantly like with a timer. Basically you have to use functions, for example, if it was a card game, you would lay all the cards and wait for user input, when the user hits the button you would run "calculate outcome function" and make the proper changes in the board and wait for the next input.
If you want to pause the thread i would assume it is because something is running constantly, there is a special timer that syncs with the screen called CADisplayLink
https://developer.apple.com/LIBRARY/IOS/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html
You can even "pause" this timer to wait for an input from the user.
BTW, if you DONT want to let the user interact with the interface until an event occurs all you have to do is, self.view.userInteractionEnabled = NO; this disables all interactions on the screen until you set it back to "YES".
EDIT 2:
The way you change the flow varies on what you are using to make your game, OpenGL? Quartz2D? simple views?
It kinda feels you are a bit lost, you might wanna start from here:
http://www.raywenderlich.com/tutorials
(Scroll down to the making games part)
It looks like you are going about this wrong. By design the main thread should not be blocked. You should use some sort of callback/delegate from your background thread to your main thread to set your tag decision. I'd provide a bit more info/examples, but I'm not really sure what you trying to achieve or where your "somewhere mid code" section takes place. I thought the main thread, but then you call a selector to be performed on the main thread.

DrawRect not called due to active main thread

I have an architecture that takes input from the mic and then performs some calculations and then should render to screen.
The issue is that calling setNeedsDisplay never triggers a call to drawRect because the main thread is running the calculations.
What would be the best way to thread this?
Create a single serial queue and dispatch the work to this background queue using GCD and dispatch the final setNeedsDisplay back to the main queue, or is there a more efficient way of doing this?
keep everything long running off the main thread. that is best in my opinion. Long running calculations are also something
try to never block the UIThread
...work to this background queue using GCD and dispatch the final
setNeedsDisplay back to the main queue, or is there a more efficient
way of doing this?
Based on your pretty vague description, I'd say what you suggested is the best approach.
And if you do this with GCD, your code will be easy to read since the blocks of work you perform are inline in your code making it easy to understand what is going on.
Create a single serial queue and dispatch the work to this background queue using GCD and dispatch the final setNeedsDisplay back to the main queue, or is there a more efficient way of doing this?
You should use the highest level API available to you. In this case, it's NSOperation or one of its subclasses. Probably, NSBlockOperation is the one you want. You should
create a block operation with the block you want executing
Set its completion handler to invoke setNeedsDisplay
Stick it on an NSOperationQueue.
The completion handler needs to invoke setNeedsDisplay on the main thread. You can do this by sending performSelectorOnMainThread:withObject:waitUntilDone: to the view e.g.
[myViewThatNeedsUpdating performSelectorOnMainThread: #selector(setNeedsDisplay)
withObject: nil
waitUntilDone: NO];
I think this is a better approach than using GCD directly because it is more in the Objective-C idiom, it separates the work you are doing from the notification at the end and gives you many more options for how things get done than raw GCD. For instance, if you want several of these things to happen sequentially, you can make some operations dependencies of others without having to write lots of code.

How to create a timer in background thread in iOS

I need to create two timers. One is on the UI thread, the other one is on the background thread. These timers are independent from each other.
Scenario that I will be using; I basically need this to test the responsiveness of UI thread. TImer in uI thread updates lastUpdatedDatetime property every 200ms in UI thread. There is also a background thread that polls this lastupdatedDatetime property every 200ms.
Does anyone know how can I achieve this?
The point of NSTimer is to be able to schedule things to be run on a thread (usually the main thread) while it is handling other events on a run loop. If all you want to do on the background thread is to poll something every 200 ms, then it is far easier to not use an NSTimer and to instead just sleep the background thread. So setup an NSTimer as usual on your main thread and on the background thread do something like:
while (stillRunning) {
usleep(200*1000);
// Do something with lastUpdatedDatetime
}
This technique is wasteful of a thread but is probably more deterministic for testing purposes than using Grand Central Dispatch.
Keep in mind if lastUpdatedDatetime is an NSDate that it should be set as an atomic property so that when you access it on the background thread you are sure to receive a valid object.
look into dispatch_async and dispatch_after
dispatch_async will let you fire off a call to another thread, this is what I use to do main thread changes.
dispatch_after will let you delay a dispatch_async for a number of seconds.
These two in conjunction will let you go back and forth between threads.
here is the documents on Grand Central Dispatch

How do I prepare my UI in a background thread?

A UIViewController takes about half a second to load its contents and appear on screen. How can I make them all load in the background and appear when they're ready?
There is a LazyTableImages sample on the Apple developer site.
It shows how to perform the heavy lifting in a background thread and update the UI on the main thread.
PerformSelectorInBackground:withObject: is a possible solution, although a more modern method would be to use asynchronous blocks. You can run code on the main thread from within these blocks to update the UI Safely.
The Concurrency Programming Guide is a good place to find more information and examples of this.
A Background Thread cant update the UI,you can perform all the processing logic in background thread and call the main thread for UI update
Example to load a tableView with Data ,use the background thread to process everything and load the Data, call [tableView reloadData] using the main thread, see Grand central Dispatching to know how to Work with Threads in IOS..
Hope it Helps
Create a GCD queue to process your work in a background thread (read the docs, because my "create" label and options may not be what you want).
You send it to the queue asynchronously, meaning that the call to dispatch_async will make appropriate arrangements for the block of code you give it to run in another thread and it will then return back to you "immediately."
All the work in the block you give it will be executed on a separate thread. Note, at the end, you do another call, this time with the well know main queue. This arranges for that code to run in the main thread, which is mandatory for any UI work.
Also, you really should read the documentation on GCD and especially blocks, because there are memory and cycle considerations. Good luck.
dispatch_queue_t workQ = dispatch_queue_create("bgWorkQ", 0);
dispatch_async(workQ, ^{
// This code is now running in a background thread.
// Do all your loading here...
// When ready to touch the UI, you must do that in the main thread...
disptach_async(dispatch_get_main_queue(), ^{
// Now, this code is running in the main thread.
// Update your UI...
});
});
dispatch_release(workQ);
The easiest way is to use NSObject's - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg You just pass it a selector and it will happy in the background and not block your UI. Be aware however that there are rules to background threads.
You shouldn't update your UI from the background thread. And you need to make sure the methods you're calling are thread safe.

Resources