| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Как сделать планировщик? |
| Автор: h2o 22.11.2005, 10:45 | ||
| Я вообще не понимаю принципа построения планировщика! есть форма, в которой условия планировщика. Всё работает по таймеру. От потока отказался, т.к. надоели ошибки разные и непонятные, которых нет в таймере. Непонятно, как мне сделать расписание, тоесть по расписанию запускать мою процедуру: 1. ежедневно - DateTimePicker1 2. раз в неделю в определённый день и время - DateTimePicker2 3. раз в месяц в определенный день и время - DateTimePicker3 При запуске проги запускается таймер и он должен проверять время и при достижении нужного запустить мою процедуру. Я НЕ ПОНИМАЮ как сделать условия!!! Процедура таймера
но это неправильно т.к sleep(edtinterval*1000); не должно быть! Нужно проверять условия так если щас время = времени указанном в планировщике и сегодня ещё процедура не зарускалась, то запустить мою процедуру, потом подождать до завтра 24 часа и опять запустить процедуру мою и так всё время. А вот как такое реализовать я не понимаю. ЭТО только 1 пример! а мне надо 3 условия реализовать: 1. ежедневно - DateTimePicker1 2. раз в неделю в определённый день и время - DateTimePicker2 3. раз в месяц в определенный день и время - DateTimePicker3 Помогите!!! З.Ы. |
| Автор: ~FoX~ 22.11.2005, 10:57 |
| А зачем вообще sleep(edtinterval*1000) ? Можн так Timer1.Interval := (edtinterval*1000); Можно проверять каждый тик таймера не насталоли время равное указанному в DateTimePicker1..2..3 etc. И если настало, то взводим программу и переставляем дату в пикерах на следующую. Да вообще полно всего можно придумать. |
| Автор: Alexeis 22.11.2005, 11:10 |
| Неплохо бы вести лог событий которые были уже запущены. |
| Автор: h2o 22.11.2005, 11:18 |
| ну я и говорю, сколько не пробовал, не получается! люди!!! |
| Автор: Alexeis 22.11.2005, 11:29 | ||
Вопрос состоит в том как реализовать
|
| Автор: ~FoX~ 22.11.2005, 11:39 | ||
Ой, забыл таймер тикает раз в секунду. |
| Автор: Snowy 22.11.2005, 11:45 | ||
А зачем изобретать велосипед? CreateWaitableTimer Устанавливаешь ему любой DateTime и говоришь "Повторять каждые N времени". |
| Автор: ~FoX~ 22.11.2005, 11:53 |
| Snowy А вроде один фиг они оба WM_TIMER ловят? Хотя я согласен это проще.... |
| Автор: Albinos_x 22.11.2005, 12:09 | ||||||||||
| 1. нужно иметь файл, где хранить данные о задании Например в формате: ( время выполнения, тип выполнения(каждый день, еженедельно...), что делать) 2. желательно создать свою структуру данных, в которую передавать задания ожидающие выполнения к примеру:
далее необходимо при загрузке создавать список (перебираешь все записи и смотришь время старта, если установленное время больше текущего, то добавляешь в список, а так же проверяешь остальные условия выполнялось не выполнялось, если раз в недёлю, то надо ли добавлять и т.д.)
желательно сделать отдельной функцией, т.к. при переходе на новые сутки, нужно будет перезаписывать этот список. допустим будешь проверять задания каждую секунду, то надо запоминать предыдущую дату, и ставить условие : если предыдущая дата отличается от текущей, то перезаписать список. При проверке времени:
такой вариант не прокатит,т.к. допустим у тебя установлено время 12.12.00 ( не буду считать, но для примера это допустим будет равно 0.51222222000000), а компьютер вернёт более точное время, допустим 0.551222222222222211 и вероятность что время совпадёт очень мала, поэтому необходимо или синхронизировать часы программы и часы системы или сравнивать строки:
ещё хочу отметить, что DateTimePicker1.date вернёт значение вместе со временем, поэтому для перестраховки желательно использовать так: Trunc(DateTimePicker1.date) то же и со временем: frac(DateTimePicker1.Time) Добавлено @ 12:12 да ещё, после выполнения необходима из списка удалять задание приблизительно так:
ЗЫ: если есть ошибки или недочёты, прошу меня простить... когда писал очень спешил |
| Автор: Snowy 22.11.2005, 12:29 | ||
Нет, это не юзер-таймер, а таймер объект ядра. У Рихтера подробно описана работа с ним. На нем построен стандартный планировщик WinXP. Кроме того, он может выводить комп из спящего режима. |
| Автор: h2o 22.11.2005, 13:03 | ||||||
DateTimePicker1.Date := Now + 1; //Плюс один день - а тут как надо? Что вместо +1? Вот так:? DateTimePicker1.Date := Now + 24часа*60минут*60секунд? Добавлено @ 13:04 Albinos_x принял к сведению! но у меня более тупо реализовано! хотя... |
| Автор: h2o 22.11.2005, 13:18 |
| Snowy А где его создавать? Как с ним работать? когда включать/выключать? и т.д.? |
| Автор: Snowy 22.11.2005, 13:26 | ||
Я же сказал - у Рихтера все подробно расписано. Найди в инете книгу: "Джефри Рихрер - Создание эффективных WIN32-приложений" в chm формате. Не раз еще пригодится. Это Библия WinAPI программиста. Про таймеры читай в главе 9. |
| Автор: FRAGNATIC 22.11.2005, 16:12 |
| ещё SetTimer мона =) |
| Автор: Albinos_x 22.11.2005, 16:48 | ||||||
1 - одни сутки.
чтобы добавить время желательно использовать EncodeTime пример:
где 5 -часы - 30 - минуты - 20 - секунды |
| Автор: h2o 23.11.2005, 11:58 | ||
| А как быть с днями недели, например если указанно, что нужно запустить мою процедуру в пятницу 13го числа в 14:00? как сделать дни недели? Добавлено @ 12:04
ага! была бы ещё она на делфи! на С++ я не шарю вообще! |
| Автор: Alexeis 23.11.2005, 12:18 | ||
Вот пример с сайта delphiword
|
| Автор: h2o 23.11.2005, 13:19 |
| а как с CreateWaitableTimer в Делфи работать? где запускать, как что там вообще делать? |
| Автор: Alexeis 23.11.2005, 17:23 |
| Посмотри http://rosigma.chat.ru/richter/head9.htm |
| Автор: h2o 25.11.2005, 11:53 |
| Дак я читал уже! Всё равно не понял! я и пример для Делфи в инете не нашёл!!! Там вообще примеров нет, а если и встречаются, то на С++. Может у кого примерчик есть? |
| Автор: h2o 25.11.2005, 17:33 | ||
упс! нашёл:
теперь непонятно ГДЕ его запускать, ГДЕ Останавливать и ГДЕ указать свою процедуру выполнить, когда он сработатет? |
| Автор: Snowy 25.11.2005, 18:04 | ||
Ну вот чисто для теста накатал:
Добавлено @ 18:05 P.S. Это пример. Он не вырубается. Бырубаем через дельфи по Ctrl+F2 или диспетчер задач. |
| Автор: h2o 28.11.2005, 12:14 |
| if Timer.Wait(1000) = wrSignaled then // Ждем ответа от таймера в течении секунды на эту строку ругается, типа "[Error] Unit1.pas(789): Undeclared identifier: 'wrSignaled'" и чё делать? Добавлено @ 12:19 ой! голова моя дырявая, разобрался! |
| Автор: sexton 28.11.2005, 12:42 |
| Может и не в тему, но советую посмотреть компоненты для планировщиков от TMS (www.tmssoftware.com) |
| Автор: h2o 29.11.2005, 09:08 |
| Snowy а как его хоть останавливать?никак не могу. всё время ошибки возникают... |
| Автор: Romikgy 29.11.2005, 12:30 | ||
|
| Автор: h2o 29.11.2005, 13:57 |
| а точно! не работало из-за неправильно организованного цикла! я ступил! |
| Автор: Демо 29.11.2005, 21:55 |
| А почему ты не хочешь свой планировщик в виде сервиса оформить? По-моему так будет логичнее. |
| Автор: h2o 30.11.2005, 11:58 |
| у меня не совсем планировщик, и он с формой! так, что сервис отпадает! блин! я уже вообще его замучился делать! нифига не получается! Вообще мне нужно, по условиям времени... заданых юзеров запускать 1 процедуру. тоесть есть варианты: 1. на определенный день в определенное время 2. автоматом каждый день 3. автоматом раз в неделю 4. автоматом раз в месяц Я пробовал делать с помощью: 1. Потока (там ошибки, зависоны), отказался от него 2. С помощью таймера (тока 1е условие реализовал, остальные не получилось) 3. С помощью WaitAbleTimer (может я там что-то и не правильно делал, но тоже не получилось) Вообщем я просто опустил руки! я непонимаю как можно реализовать условия выше. Я уже и здесь вопросы задавал и мне помогали, но так и не разобрался! А всего-то, нужно: 1. на определенный день в определенное время - если дата и время сейчас >= указанной дате и времени, то запускаем процедуру, если нет ждём 5 сек и т.д 2. автоматом каждый день - если сегодня процедура в такое-то время ещё не запускалась, тогда запускаем, если время не подошло ждем, а если запускалась, то нужно завтро и в последущие дни тоже самое делать. 3. тоже самое но не каждый день а раз в неделю (в месяц)! и т.д Я не смог правильно сделать проверку условия, а если сделать, тогда хоть всеми способами можно будет реализовать! вот такой вот я стопор! если кто-хоть когда-нибудь это делал, дайте приерчик! |
| Автор: Демо 30.11.2005, 12:52 |
| Может всё обсудим снова? 1. Зачем тебе форма? |
| Автор: h2o 30.11.2005, 12:55 |
| 1. указывать все настройки (их туча!!!) |
| Автор: Демо 30.11.2005, 12:58 | ||
Так можно отделить мух от котлет;) Сервис занимается тем, что по расписанию выполняет свои задачи, а отдельное приложение используется для настроек. Как тебе такой вариант? |
| Автор: Alexeis 30.11.2005, 13:00 |
| http://soft.mail.ru/program_page.php?grp=14368 |
| Автор: h2o 30.11.2005, 13:07 |
| по началу я тоже так хотел, но: я неумею писать сервисов и вряд ли разберусь! (хотя это вообще был бы идеальный вариант, т.к. юзер бы вообще ничего не видел.) Я думал, и мне больше по душе понравился вариант форма+трэй+поток+автозапуск проги при загрузке винды! Прога висит в трее, а поток (hThread или Таймер или WaitAbleTimer) сверяет настройки и запускает процедуру! Самое сложное- это то что я не понимаю как реализовать проверку расписания. При запуске проги она загружает из ИНИ настройки все, при закрытии записывает. Далее из формы из ее VCL компонентов берутся настройки расписания, сравниваются и если совпало-то запускается моя процедура! А вот как проверку этих условий реализовать? Вот вся проблема? |
| Автор: Демо 30.11.2005, 13:15 | ||
Это просто. Свой первый сервис я написал, просто взяв его из справки и разобравшись. |
| Автор: Farnsworth 30.11.2005, 15:17 | ||||||
+1 - это и значит добавить один день. Если тебе нужно добавить 1 час, то нужно сделать +1/24. Если одну минуту: +1/24/60. Понятно? Переменная TDateTime - это число, равное количеству дней, прошедших с 30.12.1899 (в Delphi). Если прошло пол дня, значит значение 0.5.
"Равно" конечно сравнивать нельзя, но достаточно сравнить с интервалом, равным, скажем, двум интервалам таймера (с запасом):
|
| Автор: Демо 30.11.2005, 15:49 |
| h2o Если хочешь, давай вместе напишем каркас планировщика. В случае согласия в PM дам координаты для связи. |
| Автор: h2o 30.11.2005, 16:35 | ||
Farnsworth Вот ты написал что надо так:
А я сравнивал даты! значения дат в любом случае должны совпадать, поэтому сравнение по "=" - допустимо. А вот время я сравнивал условием ">=", что должо было работать! а не работало! попробую с сравнением которое ты написал! суть то в том что непонятно как реализовать саму процедуру проверки расписания (тоесть процедуру сравнения вемени) |
| Автор: Farnsworth 1.12.2005, 06:17 | ||||
| 1. Когда-то я заметил, что DataTimePicker возвращает не только дату, но и время. Так что дату, полученную от DateTimePicker нужно приводить к 00 часам 00 минутам, то есть Date1:=int(DateTimePicker1.Date); 2. Точно не помню, но кажется функция Date тоже дает не 00 часов 00 минут, так что и её результат тоже нужно округлять: Date2:=int(Date); 3. В первом приведенном тобою коде ты использовал функцию Now - он тем-более даёт и дату и время, так что: Date3:=int(Now); 4. И вот тогда ты можешь сравнивать даты по "=". 5. Насчёт процедуры проверки времени - если у тебя проверка запуска по расписанию стоит в обработчике таймера, то достаточно использовать то, что я тебе написал выше. Кстати лучше даже сделать так:
Добавилось "*2". Винда тормозит, и таймер может сработать не через 1000 милисекунд, а 1500 или даже намного больше (например, при чтении дискеты или сбойного CD-ROM'а). Лучше интервал самого таймера поставить 10 или 20 секунд (зачем каждую секунду-то проверять, винду нагружать?). 6. Не забудь, что если у твоей программы-планировщика есть возможность что-то запускать с периодом в 1 сутки, то нужно предусмотреть такой вариант, что, к примеру, твою программу (или саму Виндоуз, если твоя программа в авто-загрузчике будет прописана) могут запустить чуть позже срока срабатывания одного из ежедневных событий, например с опозданием на 1 минуту, и тогда это событие уже никогда не произойдет. Так что в случае ежедневных заданий их нужно проверять if DailySheduledTime<=Now then begin {обработчик ежедневного события}; DailySheduledTime:=Now+1; end;. Этот пример тебе уже приводил ~FoX~. 7. Если в твоей программе есть возможность установить событие на какое-то определенное время, то по той-же причине, что и в пункте 6, оно может не сработать из-за опоздания запуска программы всего лишь в 1 минуту. По-этому в модуль запуска программы лучше поставить ещё одну процедуру проверки этих событий, но проверять уже с интервалом в, скажем, 10 минут (или лучше пускай этот "запас" устанавливает сам пользователь в "Дополнительных (advanced) настройках" каких-нибудь):
|
| Автор: Albinos_x 1.12.2005, 07:00 | ||||
не Date возвращяет чистую дату...
про это я писал в начале... |
| Автор: Albinos_x 1.12.2005, 07:19 | ||||||||
если делать сравнение:
то всё расно сработает, но в этом случае сразу после срабатывания необходимо удалять задание из списка ожидания, иначе будет постоянно выполняться.... можно конечно добавить ещё к записи признак выполнялось/невыполнялось... но это имхо не эффективно... а вот:
эт странно... попробуй в пошаговом режиме посмотреть какие данные она возвращяет и найти ошибку
эт в принципе не нужно... хотя в проге можно предусмотреть вариант с настройкой проги... допутим напоминать выполненые задания... и при загрузке проги проверять какие сегодня должны были выполниться задания и отображать список... |
| Автор: Alexeis 1.12.2005, 10:08 |
| h2o я набросал каркас планировщика без таймера, со вторым потоком. Проект сырой - нет отображения, загрузки и сохранения заданий и еще много чего но вроде то что просил... http://alexei-s1.narod.ru/Sheduler.rar |
| Автор: h2o 1.12.2005, 11:16 |
| alexeis1 ругается на RecodeMilliSecond(tt, 0); |
| Автор: Alexeis 1.12.2005, 11:27 |
| h2o на остальные не ругается? (не могу сам проверить на работе нет палитры Samples) |
| Автор: h2o 1.12.2005, 11:35 |
| вообщем, когда указываю все настройки, указываю ехе, нажимаю ОК, он говорит "invalid float point" и показывает в Delphi на эту строку, я может неправильно ввожу что? Добавлено @ 11:38 и это происходит токо когда ехе указываю. у меня в поле едит ничё не выводится... |
| Автор: h2o 1.12.2005, 11:50 |
| Нашел в чем ошибка! у тебя там переменная tt не инициализирована была. Теперь работает! вот только я ему указал запустить прогу, а он мне её раз 20 запустил (20 экземпляров), он ее запускал пока я не вырубил всё ресетом в делфе |
| Автор: Alexeis 1.12.2005, 11:56 | ||
| Дело в том что эту часть проекта вчера просто не успел отладить долго мучал потоки так что попробую исправить ошибки (вероятно есть) если можешь пришли файлик samples.bpl Добавлено @ 12:03 еше в Procedure TWorkThread.test; надо строчку заменить на pNone : incYear(ShEvents[i].Next, 100);
как инициализировал? |
| Автор: h2o 1.12.2005, 12:16 | ||
|
| Автор: Alexeis 1.12.2005, 12:40 | ||||
Я думаю что ошибка в установке даты ShEvents[Length(ShEvents) - 1].Next нашел ошибку
|
| Автор: Alexeis 2.12.2005, 10:00 |
| h2o Вот новый переработанный и улучшенный вариан планировщика Это еще не готовая программа но вроде отладил... http://alexei-s1.narod.ru/Sheduler.rar |
| Автор: h2o 2.12.2005, 13:07 |
| и опять переменная tt не инициализированна! опять ошибка как в прошлый раз! неужели у тебя всё без ошибки проходит? Ну остальное работате! смотрю дальше... спасибо Добавлено @ 13:15 он за 2 минуты 4 раза мне прогу запустил, с интервалом в 30 секунд примерно! |
| Автор: Alexeis 2.12.2005, 13:30 |
| а это и не требуется tt := RecodeDateTime(tt, t.Year, t.month, t.Day, t.hour, t.min, 0, 0); и есть инициализация Добавлено @ 13:39 3 минуты полет нормальный - один запуск (по расписанию) |
| Автор: Alexeis 2.12.2005, 13:41 |
| 5 минут полет нормальный - один запуск (по расписанию) перевожу стрелки часов на час вперед второй запуск попробуй компилировать в Delphi 7, Delphi 2005 все покидаю форум буду во вторник |
| Автор: h2o 9.12.2005, 09:10 |
| долбил, долбил, а он всё равно запускает много экземпляров указанной проги запускать! я на выходных дома попробую откомпелировать! |
| Автор: Albinos_x 9.12.2005, 09:21 | ||
видно стирать задание забываешь... |
| Автор: Alexeis 9.12.2005, 10:20 | ||
Правельно прога то недоделанная! удали ini файл и попробуй снова по порядку (так как я писал в email - e) |