Форум: "Прочее";
Текущий архив: 2009.12.13;
Скачать: [xml.tar.bz2];
ВнизХочу повесить программу, Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.007 c