Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.12.13;
Скачать: CL | DM;

Вниз

Хочу повесить программу,   Найти похожие ветки 

 
ocean   (2009-10-15 12:08) [0]

Следящую за наступлением события. Событие может происходить раз в неск.часов. Собираюсь поместить на форму TTimer, тикающий раз в 10 мин. Но хотелось бы загрузить системные ресурсы по минимуму. Как это лучше сделать?


 
DVM ©   (2009-10-15 12:09) [1]


> Но хотелось бы загрузить системные ресурсы по минимуму.
> Как это лучше сделать?

А таймер сильно грузит?


 
TUser ©   (2009-10-15 12:10) [2]

Для многих событий есть специальные средства такого рода, например, для изменений в файловой системе, - в ВинАпи.


 
DVM ©   (2009-10-15 12:12) [3]


> ocean   (15.10.09 12:08)  

У стандартного таймера есть только один существенный недостаток. Он может и не тикнуть вовремя.


 
DesWind   (2009-10-15 12:16) [4]

CreateWaitableTimer


 
Anatoly Podgoretsky ©   (2009-10-15 12:25) [5]

> ocean  (15.10.2009 12:08:00)  [0]

Так никакой нагрузки и не будет, также можешь использовать Sleep


 
Дмитрий С ©   (2009-10-15 12:58) [6]

Поток + sleep.


 
Игорь Шевченко ©   (2009-10-15 13:06) [7]

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

Написал тупо на таймере

unit main;

interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, HsObjectList, StdCtrls;

type
 TCronCommand = class
 private
   FCommandText: string;
   FInterval: TDateTime;
   FRemaining: TDateTime;
 public
   property CommandText: string read FCommandText write FCommandText;
   property Interval: TDateTime read FInterval write FInterval;
   property Remaining: TDateTime read FRemaining write FRemaining;
 end;

 TCronCommands = class(THsObjectList)
 private
   function GetItems(I: Integer): TCronCommand;
 public
   property Items[I: Integer]: TCronCommand read GetItems; default;
 end;

 TfMain = class(TForm)
   Timer1: TTimer;
   Log: TMemo;
   procedure Timer1Timer(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   FCommandList: TCronCommands;
   procedure ParseCommands;
   procedure ProcessCommand (const Command: string);
 end;

var
 fMain: TfMain;

implementation
uses
 DateUtils;

var
 TimerTick: TDateTime;

{$R *.dfm}

procedure TfMain.FormCreate(Sender: TObject);
begin
 FCommandList := TCronCommands.Create;
 Timer1.Enabled := false;
 ParseCommands;
 Timer1.Enabled := true;
 Log.Lines.Add("Scheduler started");
end;

procedure TfMain.FormDestroy(Sender: TObject);
begin
 FCommandList.Free;
end;

procedure TfMain.ParseCommands;
var
 Worker, Parts: TStringList;
 S: string;
 HH, MM, SS: Integer;
 Interval: TDateTime;
 Item: TCronCommand;
begin
 //Формат записи: every$$hh:mm:ss$$command-text
 Worker := TStringList.Create;
 Parts := TStringList.Create;
 try
   Worker.LoadFromFile(".\Schedule");
   for S in Worker do
     if Copy(S, 1, 1) <> "#" then
     begin
       Log.Lines.Add(Format("processing entry %s", [S]));
       StrBreakApart(S, "$$", Parts);
       if (Parts.Count <> 3) or (not SameText(Parts[0], "EVERY")) then
         raise Exception.CreateFmt("illegal string %s", [S]);
       HH := StrToInt(Copy(Parts[1], 1, 2));
       MM := StrToInt(Copy(Parts[1], 4, 2));
       SS := StrToInt(Copy(Parts[1], 7, 2));
       Interval := EncodeTime(HH, MM, SS, 0);
       Item := TCronCommand.Create;
       Item.Interval := Interval;
       Item.Remaining := Interval;
       Item.CommandText := Parts[2];
       FCommandList.Add(Item);
     end;
 finally
   Worker.Free;
   Parts.Free;
 end;
end;

procedure TfMain.ProcessCommand(const Command: string);
var
 si: TSTARTUPINFO;
 pi: TPROCESSINFORMATION;
 rc: Boolean;
begin
 Log.Lines.Add(Format("Executing: %s", [Command]));
 FillChar(si, SizeOf(si), 0);
 FillChar(pi, SizeOf(pi), 0);
 si.cb := SizeOf(si);
 si.dwFlags := STARTF_USESHOWWINDOW;
 si.wShowWindow := SW_HIDE;
 rc := CreateProcess(nil, PChar(Command), nil, nil, true,
   CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, si, pi);
 Win32Check(rc);
 CloseHandle(pi.hProcess);
 CloseHandle(PI.hThread);
end;

procedure TfMain.Timer1Timer(Sender: TObject);
var
 I: Integer;
begin
 for I := 0 to FCommandList.Count - 1 do
 begin
   FCommandList[I].Remaining := FCommandList[I].Remaining - TimerTick;
   if FCommandList[I].Remaining <= 0 then
   begin
     FCommandList[I].Remaining := FCommandList[I].Interval;
     ProcessCommand(FCommandList[I].CommandText);
   end;
 end;
end;

{ TCronCommands }

function TCronCommands.GetItems(I: Integer): TCronCommand;
begin
 Result := TCronCommand(inherited Items[I]);
end;

initialization
 TimerTick := EncodeTime(0, 0, 1, 0);
end.

Таймер срабатывает раз в секунду.

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


 
Anatoly Podgoretsky ©   (2009-10-15 13:12) [8]

> Дмитрий С  (15.10.2009 12:58:06)  [6]

Если поток, то зачем SLEEP


 
Anatoly Podgoretsky ©   (2009-10-15 13:19) [9]


> В свое время понадобилась запускалка программ каждые N минут(секунд,
>  часов). У стандартного планировщика минимальный интервал,
>  как я выяснил, не меньше суток (может, ошибся, буду рад
> на пинок в нужном направлении, чтобы убить изобретенный
> велосипед)

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


 
Дмитрий С ©   (2009-10-15 13:20) [10]


> У стандартного планировщика минимальный интервал, как я
> выяснил, не меньше суток

Есть повтор, можно каждые 5 минут запускать.


 
Skyle ©   (2009-10-15 13:20) [11]


> Игорь Шевченко ©   (15.10.09 13:06) [7]
> В свое время понадобилась запускалка программ каждые N минут(секунд,
>  часов). У стандартного планировщика минимальный интервал,
>  как я выяснил, не меньше суток (может, ошибся, буду рад
> на пинок в нужном направлении, чтобы убить изобретенный
> велосипед)

Это как это?

Добавить задание->Выполнять задание ежедневно->Время начала 00:00, ежедневно. Перед нажатием "Готово" ставим галочку "Установить дополнительные параметры....".

Далее закладка "Расписание". Назначить "ежедневно", жмём "Дополнительно".
Ставим галочку "повторять задание" и задаём периодичность, с которой оно будет выполняться каждый день.

Другая проблема в том, что мы отказались от штатного планировщика в районе IE5.5, потому что он иногда зависал. В какой-то момент надоело и написали свой. Как это сейчас, особенно в свете Шедулер2 из висты, я не знаю.


 
Игорь Шевченко ©   (2009-10-15 13:32) [12]

Anatoly Podgoretsky ©   (15.10.09 13:19) [9]
Дмитрий С ©   (15.10.09 13:20) [10]
Skyle ©   (15.10.09 13:20) [11]

Если не затруднит, как это в синтаксисе команды at выглядит ? (раз в 10 минут выполнить foo.exe)


 
Skyle ©   (2009-10-15 14:13) [13]


> Игорь Шевченко ©   (15.10.09 13:32) [12]
> Если не затруднит, как это в синтаксисе команды at выглядит
> ?

Ну это проблемы at, а не шедулера, другой момент.
at это вообще ущербный обрубок.
В принципе может можно поколдовать с еженедельным запуском заданий + soon.exe. Но проще наверное взять Vista/2008 и воспользоваться ITaskService.


 
Игорь Шевченко ©   (2009-10-15 14:18) [14]

Skyle ©   (15.10.09 14:13) [13]


> Ну это проблемы at, а не шедулера, другой момент.
> at это вообще ущербный обрубок.


Я располагаю только синтаксисом команды at. Если я буду вынужден передавать описание колдовства с назначенными заданиями в деревню Гадюкино Усть-Константинопольского уезда с неизвестной операционной системой там, мне проще написать программу (тем более, написание заняло полчаса)


> + soon.exe.


Что за зверь ?


> Но проще наверное взять Vista/2008 и воспользоваться ITaskService.


Есть Windows 98 и Windows NT4 (минимально сопровождаемые системы)


 
Skyle ©   (2009-10-15 14:21) [15]


> > + soon.exe.
> Что за зверь ?

Из W2k Resource Kit мелкая утилитка. Позволяет запускать задания, созданные с помощью at ..... /k через указанное количество секунд.

Но это велосипед получится, притом очень хреновый.


> > Но проще наверное взять Vista/2008 и воспользоваться ITaskService.
> Есть Windows 98 и Windows NT4 (минимально сопровождаемые
> системы)

Я отталкиваюсь вот от этой статьи
http://msdn.microsoft.com/ru-ru/magazine/cc163350.aspx


 
DVM ©   (2009-10-15 14:34) [16]

На королевстве Делфи есть статья "Таймер, который не подведет" как раз там создается планировщик со строкой конфигурирования в формате CRON


 
DVM ©   (2009-10-15 14:35) [17]

вот
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=434


 
Игорь Шевченко ©   (2009-10-15 14:44) [18]

Skyle ©   (15.10.09 14:21) [15]
DVM ©   (15.10.09 14:34) [16]

Первое, что я сделал, когда мне надо было решить задачу - изучил синтаксис команды at. Не нашел нужной мне возможности запускать каждые 10 минут (причем 10 минут - это не абсолютная точность, просто "примерно каждые 10 минут").
Второе, что я сделал - начал искать бесплатные порты Cron под Windows. Не нашел или то, что нашел, не смог запустить.
Третье - за полчаса написал свою программу и доволен.


 
Empleado ©   (2009-10-15 14:53) [19]

Я извиняюсь, я не сильно специалист, а зачем там таймер-то? (Наверняка я что-то не понял)

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


 
Игорь Шевченко ©   (2009-10-15 14:56) [20]


> Событие наступило: SetEvent


А кто его установит ?


 
clickmaker ©   (2009-10-15 15:02) [21]

> В отдельном потоке безустанно ждем это событие

чем это отличается от Sleep?


 
Empleado ©   (2009-10-15 15:03) [22]


> А кто его установит ?

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


 
Anatoly Podgoretsky ©   (2009-10-15 15:12) [23]

> Игорь Шевченко  (15.10.2009 14:18:14)  [14]

В синтаксисе at нет таких возможносте.
Но у тебя очень жесткие ограничения по ОС, поэтому легче будет написать программу.
Можно было воспользоваться scheduller API, но в 98 нет служб, да и не уверен, что вообще есть АТ


 
Anatoly Podgoretsky ©   (2009-10-15 15:25) [24]

> clickmaker  (15.10.2009 15:02:21)  [21]

Разница есть, пока ждем с помощью sleep то все в потоке заблокировано.
А так или выходим или по событию (сигнализируем) или по таймауту.


 
clickmaker ©   (2009-10-15 15:33) [25]

> пока ждем с помощью sleep то все в потоке заблокировано

а при "безустанно ждем это событие" разве нет?


 
Anatoly Podgoretsky ©   (2009-10-15 15:48) [26]

> clickmaker  (15.10.2009 15:33:25)  [25]

Конечно нет, ожидаем события в другом потоке и от туда сигналим, а в основном потоке ждем например по WaitForSingleObject С ТАЙМАУТОМ


 
clickmaker ©   (2009-10-15 16:10) [27]

> Конечно нет, ожидаем события в другом потоке и от туда сигналим,
> а в основном потоке ждем

ну так а чем это отличается от
repeat
  Sleep(ScheduleInterval);
  DoTask();
until Terminated;

?


 
KilkennyCat ©   (2009-10-15 16:23) [28]

взять настольную лампу, прикрепить к абажуру электромагнит. пока есть ток, элмаг удерживат стальной шарик. пропал ток - шарик падает, подскакивает от стола и прилетает на клавишу "Ентер".
Момент наступления исследуемого события можно отследить несколькими способами, например, приклеенным к монитору фотодатчиком или матрицей от фотоаппарата, которые отловят визуально. Если виуально событие не проявляет себя, можно ловить излучение от процессора и смотреть там. Нашей программе осталось среагировать на нажатие клавиши. Код - минимальный.


 
Anatoly Podgoretsky ©   (2009-10-15 16:23) [29]

> clickmaker  (15.10.2009 16:10:27)  [27]

Хорошо давай практически, представь себе следующую задачу.
Есть UDP клиент, которые посылает сообщение и ожидает ответа в течение 30 секунд максимум. Если запустить SLEEP(30000) то ответ придет только черз 30 секунд, тоже с самое с WaitForSingleObject.

А вот если запусить ожидание в другом потоке и просигналить по получению ответа первому потоку который ожидает сигнала WaitForSingleObject с таймаутом 30 секунд, то он проснется сразу по установке события, а не будет спать 30 секунд.

Как можешь предложить другое решение?


 
Anatoly Podgoretsky ©   (2009-10-15 16:24) [30]

> clickmaker  (15.10.2009 16:10:27)  [27]

Нужен метод SleepAndWakeup


 
clickmaker ©   (2009-10-15 16:50) [31]

> [29] Anatoly Podgoretsky ©   (15.10.09 16:23)

ну я скорей про что-то типа планировщика говорил. с фиксированным интервалом.
если есть кто-то, кто инициирует событие, то конечно лучше через event делать


 
Anatoly Podgoretsky ©   (2009-10-15 16:58) [32]

> clickmaker  (15.10.2009 16:50:31)  [31]

Ну вот опять мы про разные вещи. Но ты согласен с моим решением для данного случая.


 
qwer_qwer   (2009-10-15 19:47) [33]

Есть ещё портированный cron для Windows.



Страницы: 1 вся ветка

Текущий архив: 2009.12.13;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.02 c
2-1256149601
tata_yugay
2009-10-21 22:26
2009.12.13
событие OnRx80Full компонента СОМ


2-1256816360
Morgan128
2009-10-29 14:39
2009.12.13
Как отследить последнее действие клавы/мыши


15-1255120208
Юрий
2009-10-10 00:30
2009.12.13
С днем рождения ! 10 октября 2009 суббота


15-1255851782
POOP
2009-10-18 11:43
2009.12.13
Как сделать, что бы в FAR сохранялась


2-1256146429
madmech
2009-10-21 21:33
2009.12.13
Перестала появляться форма