How to execute a method every 5 minutes without CPU load?

Discussion in 'Mac Programming' started by Xino, Oct 13, 2008.

  1. Xino macrumors member

    Joined:
    Sep 5, 2008
    #1
    Maybe a simple question:
    I've created an application and I need some help with executing a method every 5 minutes (or so).

    My first idea about this was to create a while or for loop and increasing a variable. When the variable is high enough (lets say 10000) I execute the method and reset the timer. I think this will cause a high CPU load and besides that, there must be a nicer way to do this.

    I've some experience with threads so I'm think of something with NSThread?
     
  2. kpua macrumors 6502

    Joined:
    Jul 25, 2006
    #3
    Agreed, but if you're writing a command-line app, you'll need to start the run loop for it to work. If its a GUI app, then don't worry, AppKit started it for you.
     
  3. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    Does your program maintain state in memory that could not be persisted to a backing store? If not, i would say that having the program run the task once, then exit, would be best. Then you can use any number of scheduling tools like at or cron, or something OS X specific (i'm sure there's something) to run it every 5 minutes. Not that you should be sloppy, but this also keeps you from having to track down every memory leak, since your program does not need to run forever.

    -Lee
     
  4. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #5
    launchd?
     
  5. HiRez macrumors 603

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #6
    One thing I can tell you is that that is NOT the way to go about it; you are correct that it would be very inefficient (also, doing increments on a variable willl run at different speeds on different machines and even on the same machine depending on load, so your timing would be very erratic). As others have mentioned, NSTimer or launchd are probably your best bets. If the interval is 5 minutes I think launchd would be better, but if there's a possibility you might want a shorter interval measured in seconds, then I'd probably say a continuously running background process with a timer would be best.
     
  6. ChrisA macrumors G4

    Joined:
    Jan 5, 2006
    Location:
    Redondo Beach, California
    #8
    First you could use "cron". This is the method that UNIX has used for the last 20+ years. But it works at the appliation level. It can run a program periodically. If you can possably use this method go for it, there is near zero overhead and you don't need to write any code to use it.

    If you must manage this inside your program then the most universal way is to call sleep(). Read the sleep man page for more info.

    A related system calls are alarm() and settimer(). The select() call can be used for this purpose too.

    All of these are standard unix system calls that would work on linux or Solaris as well as Mac OS X. I try to write using things like this if i possibly can to keep the code portable.
     
  7. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #9
    Code:
    sleep (5);
    will put your application (more precise: the thread executing the call) to sleep for exactly five seconds, with zero CPU usage.
     
  8. Xino thread starter macrumors member

    Joined:
    Sep 5, 2008
    #10
    Cron or launchd are not helping with this problem because both (as far as I know) works at application level.

    Maybe this will work out indeed, I've to create a new thread and within that thread I must have a releasepool and within that releasepool a while(1) loop with a sleep(300) inside that? If this causes zero CPU load I think this will help me out :)

    The other option "NSTimer" looks useful too as far as I kan see. Is a NSTimer the same as NSThread but with a timer? Does the following code runs the method handleTimer every 0.5 seconds?

    Code:
    timer = [NSTimer timerWithTimeInterval: 0.5
                     target: self
                     selector: @selector(handleTimer:)
                     userInfo: nil
    repeats:YES];
    
    It this causes a loop and executes handleTimer every 0.5 seconds, this is definitely the way I want.
     
  9. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #11
    NSTimer does not use threads, but does do what you want.
     
  10. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #12
    This isn't quite true, from the man page:
    You have no guarantee that it will be exactly the number of seconds requested. Using usleep in tiny intervals until they add up might get you closer, but there are no guarantees there, either.

    Otherwise, the high points have been covered, but:
    this is bad times, in my opinion. Is it your expectation that your program will truly run for eternity? If not, and you have some condition inside the while that will cause you to break out of it, use that as your predicate, not 1. Even if you want to run "forever", it is still likely to be desirable that a signal can be caught and result in your loop gracefully terminating.

    -Lee
     
  11. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #13
    NSTimer is actually easier to use than a thread. If you have a Cocoa application with a run loop and event handling running, the NSTimer will basically insert a call to that selector into the run loop every 0.5 seconds. You have to worry about thread safety much less, because it is running in the main thread, along with all the other calls to your code that happen when the user moves a window, clicks the mouse, types a character on the keyboard etc.

    I would only recommend using a separate thread if the action you take every five minutes takes a long time and would interfere with the responsiveness of your application; if it executes in a separate thread, your application will always stay responsive.
     
  12. Xino thread starter macrumors member

    Joined:
    Sep 5, 2008
    #14
    Thanks all for your great help, I found out scheduledTimerWithTimeInterval was the most useful method for me...
     

Share This Page