I finally got my telnet iPhone application running to send text commands to a device i'm working on but the device isn't as fast as i would like it to be.
As of now when i press a button the phone sends a text command to the device's IP. I want to change it so that a constant process is running and checking a queue every .25 seconds. If the queue has any elements it will send, wait .25 seconds, and check again.
My initial guess is that I should check some iPhone threading libraries so that the buttons that add to queue and the send/checker method could be in separate threads.
I was looking at iOS Reference specifically at the Operation Queue and Dispatch Queue. Are these queues what I should be looking at or am i completely off here?
UPDATE:
I think i found what I want in NSThread however im reading NSMutableArray isnt thread safe. Is there a list type queue or vector that is thread safe in objective c?
UPDATE 2:
Could I use a mutablearray and put a lock{} around it everytime i add or remove objects?
You're on the right track. Running a task at a regular time interval sounds like a job for NSTimer. To get this behavior, try creating a timer like so:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(doTask) userInfo:nil repeats:YES];
Set this object to an instance variable and it will run -doTask every 0.25 seconds. As for your background operations, NSOperation and NSOperationQueue are probably your best bets. Create a custom NSOperation subclass and override the appropriate methods to run a task in the background.
GCD would be a better solution, NSTimers are not really that good for periodic tasks. Check the dispatch_after documentation.
Why not fire the command immediately via an asynchronous method?
Letting the framework handle the multithreading is almost always the right idea, in my experience.
Related
I use sleepForTimeInterval. My code
- (void)runningInBackground
{
while (1) {
[NSThread sleepForTimeInterval:waitInterval];
[self getInterval];
}
}
How can i change interval if sleepForTimeInterval is not finished?
You can not. No run loop processing occurs while the thread is blocked.
There are almost no cases where sleepForTimeInterval: is correct iOS code. iOS performs these kinds of things with NSTimer, NSOperation or GCD queues. If you find yourself calling NSThread, you are almost certainly in the wrong part of the framework.
Without knowing the details of your problem, the tool you probably want is an NSTimer. They're simple to use, and solving this kind of problem is easy with them. You just invalidate the timer and create a new one when you want to change the interval. You don't need to break out of a sleep.
But you should always ask yourself if you could turn a polling (interval-based) solution into an event-driven solution. What are you doing when you wake up? If you're usually just checking something and going back to sleep, that's very bad for the battery. iOS has good solutions for making those things event driven in most cases (so you just get called when the thing you want occurs without polling).
I have an IBAction which starts a number of timers.
I would like to have a second or a pause for a certain time. How can I pause execution?
I know of the [self performSelector:#selector(someMEthod:) withObject:someObject afterDelay:1.0];
but how can I just cause a delay without calling anything?
Thanks
You can call sleep() or +[NSThread sleepForTimeInterval:] but please don't do that on the main thread. Pausing execution of the main thread means your app's UI will be blocked for that time and appear to the user as if it had crashed. If you blocked the main thread for more than a few seconds, Apple's watchdog timer would kill your app instantly.
See this blog post by Jeff LaMarche for more on this issue: http://iphonedevelopment.blogspot.com/2010/05/psa-respect-main-thread.html
You don't want to cause a delay without calling anything. It's bad for the UI, and does not fit Cocoa Touch's event driven paradigm.
Cut the routine in which you want to pause into (at least) two parts/halves. Have the first half set up a delayed call to the second half (perform selector with delay, timer, queue, etc.) and then return to the main loop. The OS will call the second part, later, after potentially doing useful stuff in the mean time (giving the user a responsive UI or saving battery life, catching up with background email, etc.)
You may have to learn how to save state between parts (loop variables, etc.), something that some new programmers seem to miss in their learning.
You can use sleep(int_No_of_Sec); // eg. sleep(1);
I want to run a single background thread for an iPhone application which is available in background all the time and gets executed when specific event fires and go to wait for specific event to fire to start its execution again. During the execution of thread if specific event is fired again then thread should restart its work.
I am working on a custom map application. On TouchesMoved event, I need to load the map image tiles according to the positions moved in a background thread. The problem is that when I move the map with speed the touchesMoved event is fired the previous thread has not finished its work and new thread is started. It causes thread safety issue and my application is crashed.
So I am thinking of a solution to have a single thread all the time available and starts its work when touchesMoved is fired if touchesMoved is fired again it should restart its work instead of starting a new thread. I think it will prevent the thread safety issue.
Please help
Firstly I'd echo the use of NSOperation and NSOperationQueue. You could fall-back to using NSThread directly, but the point of NSOperation is that it hides threading from you, leaving you to concentrate on the processing you need to do. Try firing NSOperation requests as and when required, see what the performance is like in your use-case; even if these operations get data in an async manner, it should provide you with a cleaner solution with good performance, plus future proof.
I've successfully used NSInvocationOperation to fire requests as often as required, and it sounds like the sort-of requirements and behaviour you're after. I would suggest more generally that you experiment with these in a test project; here you can test performance.
The following weblog's helped me start playing with NSOperation:
http://www.dribin.org/dave/blog/archives/2009/09/13/snowy_concurrent_operations/
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/
As always, the Apple Threading Programming Guide is a key read, to figure out which way to go depending on needs.
This sounds like an ideal job for an NSOperationQueue. Have a read of the operation queue section of the concurrency guide.
Essentially, you create an NSOperation object for each map tile load and place them on a queue that only allows them to execute one at a time.
Put a run loop in your background compute thread. Then use an NSOperation queue to manage sending messages to it. The queue plus the run loop will serialize all the work requests for you.
I made a game that uses many timers throughout the code. However the timer has to deal with many tasks in such a small amount of time which leads to the problem where there is lag in my game. For example, my timer runs at an interval of (0.05) and it needs to draw and update many of the images on the screen. Is there any way I can distribute the work flow so that the program runs much smoother?
Thanks
Kevin
I would use an NSThread instead of an NSTimer. I have had more success in this area using NSThread because it runs on an independant thread and is not fired off your main ui thread. In the loop for the thread sleep it for 1/20 (your 0.05) of a second. Because the thread is not running on the UI thread all of its tasks should not slow your UI down. However beacsue it is not running on the UI you will have to call performSelectorOnMainThread to get the UI to update from this background thread. I put a lock on my update method (a simple boolean) that says if the last ui update has not happened, just skip this one. then if im running out of processing time i just drop a frame or two here and there. I also do a lot of checking to see if anything has actually changed before i redraw.
Simple solution: Ditch NSTimer.
Move your redrawing code to a single method, then use CADisplayLink. The issue with using your NSTimer approach is that everything is being redrawn too fast or too slow for the screen. By using CADisplayLink, you can synchronize your redraw code to the screen refresh rate. All you need to do then is touch up your code so that it can deal with not being called at a specific time.
And yes, check to make sure you don't need to redraw as Aran Mulholland said above. Just make sure the checks don't take as long as a redraw.
And remember to optimize your code. A lot. Use ivars to access objects, but the whole property (self.myObject =) to set your objects.
I have an app which gets some data from the web via an XML document. I have this working fine and have followed apples SeismicXML example (uses NSURLRequest etc). I am very new to this so I have to admit that I do not totally understand all the code that gets the XML - but it is working. My problem is that my app may be running for some time so I want to be able to refresh the XML every now and again and check to see if it is different. If it is different I need to update my contents. Basically this means my questions are....
Is there a standard way of doing this?
I was thinking of creating a timer to call the function which parses the XML but I can't figure out which function to call.
If anyone can give me any pointers or even better examples of this it would be fab. Thanks
An NSTimer is the way to kick off a process that needs performing every x seconds
[NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(theXMLMethod)
userInfo:nil
repeats:YES];
This sets a timer of 5 seconds that calls the theXMLMethod method.