Самый безопасный способ простоя приложения Delphi, чтобы дождаться таймера?

Я делаю приложение Delphi, которое будет работать на моем компьютере 24/7 в фоновом режиме и будет проверять, нужно ли ему выполнять какие-то действия или нет, ждать 30 минут и снова проверять и так далее.

Как я могу убедиться, что приложение не будет перегружать процессор или память из-за того, что оно работает все время.


person Sebastian    schedule 13.05.2010    source источник
comment
Как освободить/перераспределить память?   -  person Sebastian    schedule 13.05.2010
comment
Если у вас нет утечки памяти, не беспокойтесь о памяти. Если у вас ДЕЙСТВИТЕЛЬНО есть утечка памяти, исправьте ее. SysInternals — ваш друг.   -  person Chris Thornton    schedule 13.05.2010
comment
Запуск вашего приложения уже является пустой тратой ЦП и времени, используйте планировщик Windows, как предлагает парень ниже!   -  person Warren P    schedule 14.06.2010


Ответы (7)


В большинстве языков программирования есть функция «сна», которую вы можете вызвать, чтобы программа перестала что-то делать.

Вы контролируете использование памяти; вы можете освободить свою память перед сном и перераспределить ее при пробуждении, но...

Может быть, лучше просто настроить повторяющуюся работу. Я не знаю, как это сделать, но подозреваю, что с помощью Windows Scripting Host можно просто запускать приложение по любому расписанию.

person dash-tom-bang    schedule 13.05.2010
comment
У вас есть пример того, как освободить/перераспределить память в Delphi? - person Sebastian; 13.05.2010
comment
@Sebastian: вы освобождаете память, освобождая объекты, и перераспределяете ее, создавая новые. (Это немного сложнее, но это основная идея.) Я думаю, что он имеет в виду здесь то, что вы должны убирать за собой перед сном и воссоздавать свои объекты, когда событие снова срабатывает. - person Mason Wheeler; 13.05.2010
comment
Ну, я не думаю, что вы обязательно должны убирать за собой и восстанавливать все заново, когда проснетесь. Действительно, если вы собираетесь это сделать, просто перезапускайте приложение каждые 30 минут. Предположительно, хотя приложение можно было бы сделать так, чтобы ему вообще не требовалось много постоянного состояния. - person dash-tom-bang; 14.05.2010
comment
Используйте планировщик Windows и завершите свое приложение, когда закончите свою задачу. Более чистый способ ИМО. - person Francesca; 14.05.2010
comment
Я использовал планировщик Windows несколько раз, как для периодического запуска чего-либо, так и во вторую очередь, чтобы убедиться, что что-то продолжает работать, если кто-то его выключит. Убедитесь, что вы проверили, запущено ли ваше приложение (вероятно, не хотите, чтобы два из них работали), и просто вызовите приложение с любыми параметрами, которые вам могут понадобиться. Убедитесь, что он работает с достаточными разрешениями для выполнения своей работы. Очень просто. - person Doug Johnson-Cookloose; 14.05.2010
comment
Использование Sleep в течение примерно 30 минут, вероятно, не очень хорошая идея, так как это полностью зависнет в основном потоке, и приложение не будет отвечать. - person jpfollenius; 14.05.2010
comment
Как сказал @Smasher, Sleep не является правильным решением. Если ваше приложение делает что-то для использования ЦП и памяти, когда оно должно простаивать, вам следует выяснить, почему это происходит, и исправить это. - person Igby Largeman; 14.05.2010
comment
Я согласен, что спать 30 минут неоптимально, но если у приложения нет пользовательского интерфейса, это не имеет значения. В OP это звучало как приложение, у которого не было пользовательского интерфейса, или, по крайней мере, такое, в котором работника можно было убирать на 30 минут за раз... - person dash-tom-bang; 14.05.2010
comment
Используйте SleepEx, его можно прервать. Длительный сон затруднит завершение работы вашей программы. - person Warren P; 14.06.2010

Создайте таймер, который будет запускаться каждые 30 минут, и оттуда вызывайте свои проверки/действия. Тогда ваше приложение может просто простаивать, когда ему нечего делать.

В качестве альтернативы вы можете создать запланированную задачу, которая просто периодически запускается для этого.

person Justin Ethier    schedule 13.05.2010
comment
Использование планировщика Windows - лучший вариант. Вашему приложению не нужно находиться в памяти, когда оно ничего не делает. Там и так слишком много дерьма осталось... - person Francesca; 14.05.2010

Ответы о таймерах являются хорошими решениями, и я добавлю следующее: убедитесь, что событие таймера или последующая вызываемая процедура проверяет занятость. то есть, если вы просыпаетесь, убедитесь, что последняя партия сделана, прежде чем начинать новую партию. Это легко пропустить, когда все идет хорошо, и тогда у вас возникает ситуация, когда все резервируется, и вся система зависает в 8 утра, потому что что-то плохое произошло в полночь, и теперь есть 16 вызовов (или потоков). , процессы и т. д.).

Итак, напишите свое событие таймера следующим образом:

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;
person Chris Thornton    schedule 13.05.2010

Ответы о таймерах в значительной степени именно то, что вы ищете. Что касается вашего вопроса о том, чтобы не перегружать процессор или память, взгляните на свою программу в диспетчере задач. Когда он ничего не делает, он должен находиться в «устойчивом состоянии» памяти, больше не выделяя и используя 1% или меньше процессорного времени.

Безопасно оставлять большинство программ бездействующими в течение длительного времени. VCL знает, как справиться с бездействием, не перегружая ресурсы ЦП, и вам просто нужно использовать таймер, чтобы убедиться, что он просыпается и активирует свое событие в нужное время.

person Mason Wheeler    schedule 13.05.2010

Если вы хотите обеспечить абсолютное состояние бездействия, я думаю, вы могли бы использовать функцию «сна». Хотя я не уверен, как он поведет себя при перезагрузке. (Я предполагаю, что Windows сообщит о том, что приложение не отвечает.)

Если приложение не имеет основной формы и просто находится в трее (или полностью невидимо), оно мало что даст. Основной цикл обработки сообщений будет обрабатывать все сообщения, которые он получает от ОС, но не должен получать много сообщений. И несколько сообщений, которые он получит, он должен их обработать (сообщения о завершении работы, уведомление об изменении параметров системы и т. д.)

Итак, я думаю, вы могли бы просто установить таймер и забыть о настройке кода, заставляющего вашу программу простаивать.

Если вы действительно хотите максимально ограничить эту активность процесса, вы можете установить приоритет потока при входе/выходе события таймера. Таким образом, вы должны установить приоритет на «нормальный» при входе в событие и установить его на «Низкий» при выходе из него.

person Ken Bourassa    schedule 13.05.2010

Вы не сказали, но если ваше приложение использует более одного потока, это может увеличить количество ЦП, которое ОС тратит на ваш процесс (например, прочитайте о временных срезах и переключениях потоков).

ОС также может подкачать некоторые из ваших страниц памяти, таким образом, используя меньше памяти и/или сокращая доступ к памяти в «время ожидания».

Таким образом, если вы используете только один поток и не имеете дополнительных циклов обработки сообщений, просто вызов Sleep() может быть хорошим способом, так как это будет сигнализировать ОС о том, что вам вообще не нужен временной интервал в течение длительного времени, чтобы приходить.

Избегайте YieldThread()/SwitchToThread() и вашего собственного хронометража (например, используя Now()), так как это будет означать, что происходит много переключений потоков, чтобы не делать.... ничего!

Другим методом может быть использование WaitForMultipleObjects с большой тайм-аут, поэтому ваше приложение все еще может отвечать на сообщения.

person PatrickvL    schedule 17.05.2010

Я бы предложил создать сервисное приложение (установить автоматический тип запуска) и использовать CreateTimerQueueTimer в качестве таймера. Утечки памяти можно уменьшить, зарезервировав требования к памяти/классы пула.

person Nige    schedule 26.05.2010