views:

301

answers:

8

I am doing a delphi application that will run on my pc 24/7 in the background and will check if it has to do some actions or not, wait 30 minutes and check again, and so on.

How can I make sure the application will not overload cpu or memory because of being running all the time.

A: 

Most programming languages have a "sleep" function that you can call to make the program stop doing stuff.

You are in control of the memory usage; you can deallocate your memory before going to sleep and reallocate it when coming awake, but...

It might be better to just set up some recurring job. I don't know how to do this, but I suspect there's a way with Windows Scripting Host to just launch your application on whatever schedule you want.

dash-tom-bang
Do you have an example of how to deallocate/rellocate memory in delphi?
Sebastian
@Sebastian: You deallocate memory by freeing objects, and you reallocate it by creating new ones. (It's a bit more complicated than that, but that's the main idea.) I think what he means here is that you ought to clean up after yourself before sleeping, and recreate your objects when the event fires again.
Mason Wheeler
Well- I don't think that you necessarily *should* clean up after yourself and rebuild everything when you wake. Indeed, if you're going to do that, just relaunch the application every 30 minutes. Presumably though the application could be made so that it doesn't need to have a lot of persistent state in the first place.
dash-tom-bang
Use the windows scheduler and have your application terminate when done with its task. The cleaner way IMO.
François
I've used the Windows Scheduler several times, both to run something periodically and secondarily to make sure that something continues to run if someone shuts it off. Make sure you check to see if your application is already running (probably don't want two of them going) and just call the application with any parameters you may need to pass. Make sure it runs with enough permission to do its job. Easy Peasy.
Doug Johnson
Using `Sleep` for a time like 30 minutes is probably not a good idea, since it will completely hang up the main thread and the app will not be responsive.
Smasher
As @Smasher said, Sleep is not the right solution. If your application is doing something to use CPU and memory when it should be idle, then you should find out why and fix it.
Charles
I agree that sleeping for 30 minutes is suboptimal, but if the application has no UI it shouldn't matter. The OP made it sound like an app that didn't have a UI, or at least one where the "worker" could be "put away" for 30 minutes at a time...
dash-tom-bang
Use SleepEx, it is interruptable. A long sleep will make your program harder to shut down.
Warren P
+12  A: 

Create a timer to run every 30 minutes, and call your checks/actions from there. Then your application can just sit idle when there is nothing to do.

Alternatively you could create a Scheduled Task that just runs periodically to do this.

Justin Ethier
Using the windows scheduler is IMO the better option. Your application does not need to reside in memory when doing nothing. There is already too much crap lingering ...
François
A: 

If my memory serves me, doesn't Delphi come with a TTimer component? That should do exactly what you need - just set the interval to 30 minutes and trigger your actions from the event that the TTimer raises every interval.

Charles
Yes, Delphi has a TTimer component. Keep in mind that it is a message-based timer, so the thread that owns the timer needs an active message queue so TTimer can process its WM_TIMER messages.
Remy Lebeau - TeamB
+1  A: 

The answers about timers are pretty much exactly what you're looking for. As for your question about not overloading the CPU or memory, take a look at your program in the Task Manager. When it's not doing anything, it should sit at a "steady state" of memory, not allocating any more, and using 1% or less of CPU time.

It's safe to let most programs idle for long periods. The VCL knows how to handle the idling without hogging CPU resources for you, and you just need to use a timer to make sure it wakes up and activates its event at the right time.

Mason Wheeler
+5  A: 

The answers about timers are good solutions, and I add this: Make sure that the timer event, or subsequent procedure called, checks for busy. i.e. if you wake up, make sure that the last batch is done before starting a new batch. This is easy to miss when things are flowing well, and then you have a situation where things are backed up and the whole system logjams at 8 in the morning because something bad happened at midnight and now there are now 16 calls stacked up (or threads, processes, etc..).

So write your timer event like this:

OnMyTimer...
begin
  MyTimer.Enabled := false;
  try
    DoSomethingForALongTime;  // Usually runs in 45 seconds, but sometimes takes 45 minutes!
  finally
    MyTimer.Enabled := true;  // and (SomeAbortRequest = False) and (SomeHorribleErrorCount = 0);  
  end;
end;
Chris Thornton
You need a try/finally here!
Jeroen Pluimers
@Jeroen, yes thanks.
Chris Thornton
A: 

If you want to enforce an absolute state of inactivity, I guess you could use the "sleep" function. Though I'm not sure how it would behave on a reboot. (I guess Windows would report the application as being unresponsive.)

If the application has no main form and just sitting in the tray (Or being totally invisible), it won't do much. The main message loop will handle all message it receive from the OS, but it shouldn't receive many. And the few message it will receive, it should process them (Shutdown messages, System parameters change notification, etc)

So, I think you could just set up a timer and forget about setting code to force your program to stay idle.

If you really want to limit that process activity to a maximum, you could set the thread priority when you enter/leave the timer's event. So you would set the priority to "normal" when you enter the event, and set it to "Low" when getting out of it.

Ken Bourassa
A: 

You didn't tell, but if your application uses more than one thread, this could add to the amount of CPU the OS spends on your process (read up on time slices and thread-switches for example).

The OS may also swap out some of your memory pages, thus using less memory and/or reducing memory-accesses in the "wait-time" helps too.

So, if you use only one thread and have no additional message-loops either, just calling Sleep() could be a good way, as that will signal the OS that you don't need a time slice at all for a long while to come.

Avoid YieldThread()/SwitchToThread() and your own time-keeping (using Now() for example) as that would mean lots of thread-switching is taking place, to do .... nothing!

Another method could be to use WaitForMultipleObjects with a large timeout, so your application can still respond to messages.

PatrickvL
A: 

I would suggest creating a service application (set startup type as automatic) and use CreateTimerQueueTimer as your timer. Memory leaks can be mitigated by reserving memory requirements/pooling classes.

Nige