Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизПрощу помощи разобраться со службой. Найти похожие ветки
← →
Lamer6666 (2012-06-17 09:23) [0]Доброго времени суток уважаемы.
Начал осваивать службы на основе VCL (WinAPI пока сложновато.)
Прочитал статью на королевстве о создании служб (события, методы) но в целом представление не сложилось.
1. Создал ServiceAplication
2. Скомпилировал
3. service1.exe /install служба появилась в остановленном виде.
Далее как я понимаю необходимо использовать OnStart. Согласно статье тут нужно запускать потоки.
Можно нечто блок схемы функционирования сервиса и поток в нем привести?
Например я понимаю так, исходя из моей задачи:
С разделе OnStart запускаю таймер (пока не представляю как), и по таймеру выполняю например чтение строки из файла 1.txt и запись ее в 2.txt. Так мой сервис работает целый день. Что указать по событию onStop?
Прошу прощение за мое не понимание, и возможно не правильную формулировку, прошу помощи!
← →
Loginov Dmitry © (2012-06-17 09:38) [1]
> С разделе OnStart запускаю таймер (пока не представляю как)
См. св-во TTimer.Enabled
> Что указать по событию onStop?
В случае таймеров можно ничего не указывать. В случае потоков - разместить код для их корректного завершения.
← →
Давайте будем жрать! (2012-06-17 09:42) [2]Пока что тебе достаточно написать свой код в обработчике OnExecute. Что-то вроде
while not Terminated do begin
ReadLn(F1, S);
WriteLn(F2, S);
end;
← →
Lamer6666 (2012-06-17 10:00) [3]
> В случае таймеров можно ничего не указывать. В случае потоков
> - разместить код для их корректного завершения.
А вообще как я понимаю сервис запускается при старте системы выполнив код OnStart, затем что происходит? Сервис завершает работу выполнив OnStop и все после служба остановлена?
← →
Lamer6666 (2012-06-17 10:10) [4]
> Пока что тебе достаточно написать свой код в обработчике
> OnExecute. Что-то вроде
> while not Terminated do begin
> ReadLn(F1, S);
> WriteLn(F2, S);
> end;
Ну ведь здесь мы не можем указать периодичность исполнения кода. (
← →
Давайте будем жрать! (2012-06-17 10:39) [5]while not Terminated do begin
ReadLn(F1, S);
WriteLn(F2, S);
Sleep(X); //а так?
end;
← →
Lamer6666 (2012-06-17 10:44) [6]
> while not Terminated do begin
> ReadLn(F1, S);
> WriteLn(F2, S);
> Sleep(X); //а так?
> end;
Ненужно ли сюда добавить нечто вроде Application.ProcessMessages после Sleep?
← →
Медвежонок Пятачок © (2012-06-17 10:50) [7]началось.....
там где должен быть полезный код вставляем всякую хренотень.
а полезный код за каким-то лешим в обработчик таймера суем.
как учили в автошколе.
← →
sniknik © (2012-06-17 10:58) [8]> Согласно статье тут нужно запускать потоки.
вранье, или ты врешь что там так написано. нет, там можно запускать потоки, если по логике программы требуется, но не нужно.
> Ненужно ли сюда добавить нечто вроде Application.ProcessMessages после Sleep?
ты вообще чему нибудь учишься? тебе же уже объясняли про ProcessMessages, почему его и в обычном то приложении в большинстве случаев нельзя использовать . что уже говорить про потоки/сервисы.
← →
Lamer6666 (2012-06-17 11:11) [9]
> ты вообще чему нибудь учишься? тебе же уже объясняли про
> ProcessMessages, почему его и в обычном то приложении в
> большинстве случаев нельзя использовать . что уже говорить
> про потоки/сервисы.
Просто я из тех соображений, что сервис должен подавать признаки жизни (ProcessRequests(WaitForMessage: Boolean) — обычно используется в OnExecute для получения и обработки сообщений от SCM. Некий аналог Application.ProcessMessages......) как сказано тут http://delphikingdom.ru/asp/viewitem.asp?catalogid=1348
← →
Lamer6666 (2012-06-17 11:12) [10]
> началось.....
> там где должен быть полезный код вставляем всякую хренотень.
>
> а полезный код за каким-то лешим в обработчик таймера суем.
>
> как учили в автошколе.
Ну так объясните пожалуйсто что полезно что нет.
← →
Медвежонок Пятачок © (2012-06-17 11:15) [11]сначала объясни зачем тебе таймер. можно даже не мне, а себе.
← →
Lamer6666 (2012-06-17 11:25) [12]Ну в целом задача такова:
Каждые пол минуты необходимо опрашивать БД или файл с данными. Если есть новые данные, то отправлять GET запрос на добавление этих данных стороннему WEB серверу. Посему решил реализовать сие в сервисе, что бы сервис стартовал вместе с ОС и каждую минут выполнят выше указанные действия.
На счет потоков спрашивал потому что GET запросы планировал осуществлять в потоке так как GET запросы может выполняться значительно время (не знаю верно ли это но я учитываю что сервис должен уведомлять систему о своем состоянии, ведь GET может длиться долго)
Примерно так.
← →
Медвежонок Пятачок © (2012-06-17 11:31) [13]и зачем здесь таймер?
потому что надо "раз в минуту", а на нем часики нарисованы?
← →
Lamer6666 (2012-06-17 11:38) [14]
> и зачем здесь таймер?
> потому что надо "раз в минуту", а на нем часики нарисованы?
>
Прошу прощения, видимо это стереотипы программирования раз надо что то выполнять через определенные промежутки времени, то для этого есть TTimer. К тому же TTimer не "подвешивает" исполнение когда и приложение как sleep.
Одно дело система приложение работает и считает таймером а другое дело она просто спит, мне кажеться это не совсем верно.
Может наверное я что то и не понимаю.
← →
sniknik © (2012-06-17 13:09) [15]> как сказано тут
не совсем корректно сказано, ИМХО, тем более вырванное из контекста, можно подумать что функции предлагают пихать в цикл потока, когда на самом деле там речь о "диспетчеризации" событий, отсутствующих в потоке, без самостоятельного написания.
← →
sniknik © (2012-06-17 13:18) [16]> раз надо что то выполнять через определенные промежутки времени, то для этого есть TTimer.
> К тому же TTimer не "подвешивает" исполнение когда и приложение как sleep.
sleep не подвешивает, он отдает управление другим потокам, если ты его в основном "зарядишь" то будет вид что висит...
но дополнительные для того и делают, чтобы они работали параллельно основному... ну и что что доп поток подождет чуток? на основной это влиять не должно (если написано правильно) и никаких зависаний не будет.
а сервис по сути это просто поток... присмотрись внимательнее на методы. другое дело он взаимодействует с диспетчером служб... отвечает на запросы типа "ты еще жив?" и если занять надолго, и не ответить...
← →
Lamer6666 (2012-06-17 14:17) [17]Огромное спасибо sniknik
Картина проясняется понемногу, в целом понял реализацию свое задачи так:
1. Запускаю сервис
2. В по старту начинаю проверять файл или таблицу в БД
3. Если есть новые записи, то создаю доп.поток который методом GET отправляет запрос.
и так по циклу, правильно ли я понимаю?
только не понятно все же как создать цикличную проверку БД или файла в сервисе по старту?
← →
sniknik © (2012-06-17 15:10) [18]> правильно ли я понимаю?
неправильно.
метод старт в потоке сервиса предназначен для проверки возможности работы и ответа диспетчеру служб об этом. протормозишь не запустит по таймауту.
закрытие для такого же правильного завершения с оповещением.
вся работа/циклы, как и в простом потоке ведется в execute. в цикле тогда должна быть обработка (диспетчеризация) событий... т.к. одно из событий это запрос "ты жив?" от диспетчера служб... протормозишь значит висит, будут "санкции".
в ссылке про такую модель написано, и там же про вторую (или наоборот первую, чисто пролистал).
- запустить свой поток в старте (без тормозов, помнишь? поэтому поток, а не какие то действия) и вся работа уже в нем. execute тогда не назначается, и используется дефаултный в предке, где кроме цикла с диспетчером событий ничего нет.
← →
Lamer6666 (2012-06-17 19:20) [19]Огромное спасибо sniknik и всем другим ответившим мне, еще раз перечитал статью, наверное стоит начать работу с события OnExecute как было предложено выше:
while not Terminated do begin
ReadLn(F1, S);
Try
Тут отправка данных методом GET
Finally
ReportStatus
End;
Sleep(X);
end;
но насколько корректно будет вести себя с служба при длительном GET?
← →
sniknik © (2012-06-17 19:34) [20]в показанном варианте совсем не корректно, даже без GET.
> в цикле тогда должна быть обработка (диспетчеризация) событий...
+ если есть сомнение в том, что операция не вложится в таймаут то лучше делать дополнительный рабочий поток.
← →
Lamer6666 (2012-06-17 19:49) [21]
> + если есть сомнение в том, что операция не вложится в таймаут
> то лучше делать дополнительный рабочий поток.
Вот поэтому я и склонялся больше в сторону реализации на основе событий OnStart/OnStop где все GET запросы хочу оформлять в доп. потоке, а основной поток уже избавлен от подобных операций.
Не могли бы вы дать ссылку на простенький пример реализации службы на основе событий OnStart/OnStop? Что бы можно было наглядно разобраться что к чему?!
Заранее премного благодарен.
← →
sniknik © (2012-06-17 20:14) [22]> Не могли бы вы дать ссылку на простенький пример реализации службы на основе событий OnStart/OnStop?
вопрос, где бы ее взять ссылку то? чтобы дать тебе... дай ка догадаюсь, предлагаешь поискать за тебя????
+ на "основе событий" звучит как идиотизм... нет такого, просто в ссылке было описано 2 модели, примерных, как можно сделать. но вообще без разницы, где вызывать поток если он нужен... с тем же успехом его можно начать в execute.
это к тому, если искать в гугле то просто пример службы, если добавить "на основе событий OnStart/OnStop" то скорее всего ничего не найдешь.
← →
Сергей М. © (2012-06-18 20:15) [23]
> запросы хочу оформлять в доп. потоке, а основной поток уже
> избавлен от подобных операций
Интересно, и чем же таким архиполезным занят основной поток твоего сервис-приложения ?
← →
Lamer6666 (2012-06-18 21:44) [24]Основной поток производит чтение из БД или ФАЙЛА данных каждые 5 секунд. Если есть новые записи в БД или ФАЙЛЕ то создает доп. поток отправляющий эти новые данные методом GET на сторонний сервер.
Т.е. взял данные отправил в доп. поток, прошло 5 сек взял данные отправил в доп. поток и т.д. таки образом основной поток не ждет пока выполниться GET (ведь он может не уместиться в интервал таймера)
Ну и плюс буду контролировать количество созданных потоков.
Разве не верный подход?
← →
DVM © (2012-06-18 22:07) [25]Я бы всю полезную работу сервиса делал в отдельном потоке. Так и универсальнее, в случае чего можно программу и в консольное приложение превратить (можно даже комбинированное) и в демон (под никс) и вероятность воздействия на работу службы минимальна. Причем запускать/останавливать свои потоки надо именно в OnStart OnStop событиях сервиса именно там сервис умеет обрабатывать длительный старт или длительную остановку, что позволяет оставаться не прибитым. В OnExecute можно оставить минимум кода.
← →
Сергей М. © (2012-06-18 22:40) [26]
> Lamer6666 (18.06.12 21:44) [24]
Все это расчудесно делается прямо в обработчике OnExecute, который исполняется в доп.потоке.
← →
Lamer6666 (2012-06-18 22:51) [27]Я реализовал следующим образом:
1. На TService кинул таймер
2.procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
AfterInstall(Sender);
end;
3. Создаю/проверяю файлик к который буду писать текст
procedure TService1.ServiceAfterInstall(Sender: TService);
var
path: string;
begin
Path:= ExtractFilePath(Application.ExeName) + "File.txt";
AssignFile(F,Path);
if FileExists(path) then
Append(f)
else
Rewrite(f);
end;
4. Осуществляю запись:
procedure TService1.Timer1Timer(Sender: TObject);
begin
Writeln(f,DateTimeToStr(Now)+": Проверка на запись.");
end;
сильно не ругайте, так как код пробный... хотелось бы услышать ваше мнение.
← →
Давайте будем жрать! (2012-06-19 07:43) [28]
> хотелось бы услышать ваше мнение
Работа с файлами через файловые переменные — прошлый век.
← →
Lamer6666 (2012-06-19 09:01) [29]
> Работа с файлами через файловые переменные — прошлый век.
Ну я не про файлы, а про реализацию службы. ))
← →
sniknik © (2012-06-19 09:36) [30]> Ну я не про файлы, а про реализацию службы. ))
в показанном нет НИЧЕГО от реализации службы. - все случайные совпадения, имена и события вымышлены... или как то так.
вот реально думаешь, что елинственное имя функции ServiceStart, это реализация???
← →
Lamer6666 (2012-06-19 10:12) [31]Да я ничего не думаю, нигде нет толковых примеров (как слепой тыкаюсь туда сюда), в итоге как смог так и написал, поэтому прошу подсказки что именно переделать необходимо?
Мой пример работает и начинает запись по таймеру после запуска службы.
Так что не верное реализовано, что надо переделать??
← →
Сергей М. © (2012-06-19 11:30) [32]
> На TService кинул таймер
И события таймера у тебя при этом обрабатываются в осн.потоке.
А вот если ты создашь (и уничтожишь потом соотв-но) таймер в OnExecute, то работать он будет именно в доп.потоке.
Остается организовать цикл диспетчеризации сервисных и таймерных сообщений.
← →
Lamer6666 (2012-06-19 12:26) [33]В принципе я так и планирую что таймер в основном потоке вертеться будет, опрашивать БД/ФАЙЛ
Если появились новые записи то что то в роде:
NewThread1:=TThread.Create(true);
NewThread1.FreeOnTerminate:=true;
NewThread1.Priority:=tpLowest;
NewThread1.Resume;
в NewThread1 буду выполнять отправку методом GET.
или не верное мыслю?
← →
CRLF (2012-06-19 12:59) [34]
> Lamer6666 (19.06.12 12:26) [33]
Подумай, что будет, если более поздний вспомогательный поток отработает раньше более раннего и приемлемо ли такое поведение.
← →
DVM © (2012-06-19 13:14) [35]
> Lamer6666 (19.06.12 12:26) [33]
> В принципе я так и планирую что таймер в основном потоке
> вертеться будет, опрашивать БД/ФАЙЛ
> Если появились новые записи то что то в роде:
>
> NewThread1:=TThread.Create(true);
> NewThread1.FreeOnTerminate:=true;
> NewThread1.Priority:=tpLowest;
> NewThread1.Resume;
Не проще ли выхинуть нахрен таймер, как чуждый службам элемент, а всю работу выполнять в потоке, тем более, что изменения в файле легко отслеживать с пом ReadDirectoryChangesW + WaitForXXX функций. Поток сам будет просыпаться в нужные моменты и делать необходимую тебе работу.
Для БД в том же потоке можно подписаться на уведомления (если сервер СУБД их поддерживает) или просто периодически опрашивать базу.
← →
DVM © (2012-06-19 13:22) [36]
> NewThread1.FreeOnTerminate:=true;
словишь ты тут проблем
← →
Dennis I. Komarov © (2012-06-19 14:32) [37]1. Сперва напиши не службу, а обычное приложение вынеся логику в отдельные потоки.
2. Основной поток службы - не про Вашу честь, и нечего туда пихать свой код.
← →
Dennis I. Komarov © (2012-06-19 14:34) [38]
> словишь ты тут проблем
Смотря что делает поток...
А чего ловить-то будет? "Влада"? :)
← →
DVM © (2012-06-19 15:53) [39]
> Dennis I. Komarov © (19.06.12 14:34) [38]
> Смотря что делает поток...
Судя по его описанию он у него выполняет как минимум HTTP GET запросы и запросы к базе данных. Следовательно, теоретически, может получиться, что выполнение повиснет на Connect (а это в случае блокирующих сокетов секунд 20 минимум), если в этот момент кто-то решит перезапустить или остановить службу, поток не сможет завершиться вовремя, а служба при таком раскладе его ждать не будет, все аварийно будет прибито и выскочит наверняка AV.
← →
Dennis I. Komarov © (2012-06-19 16:12) [40]
> DVM © (19.06.12 15:53) [39]
Если все будет прибито, кто к объекту обращаться будет для AV?
← →
KSergey © (2012-06-20 11:06) [41]
> Lamer6666 (17.06.12 11:25) [12]
> Ну в целом задача такова:
> Каждые пол минуты необходимо опрашивать БД или файл с данными.
> Если есть новые данные, то отправлять GET запрос на добавление
> этих данных стороннему WEB серверу.
Я такие задачи решаю написание обычной консольной программы (можно и не консольной, конечно, а обычной, с GUI, но смысла в тут GUI нет никакого). Эта программа делает все полезное (прочитать, отправить и т.д.).
Через sheduler windows (который "назначенные задания" в русской виндовс называется) настраиваю запуск этой программы с нужной периодичностью. Все, никаких сервисов не нужно.
Основным плюсы вижу следующее. Стабильность работы такой конструкции получается существенно выше, т.к. даже если программа грохнулась - в следующий раз она все равно запустится и, возможно, даже отработает корректно. Т.е. требования к требуемому качеству существенно ниже, соответственно структура и написание такой программки - несоизмеримо проще.
Время запуска ставим в значение "при включении компьютера" - тогда будет молотить круглосуточно. Правда чаще 1-го раза в минуту запуск настроить нельзя.
← →
Lamer6666 (2012-06-20 13:06) [42]
> А вот если ты создашь (и уничтожишь потом соотв-но) таймер
> в OnExecute, то работать он будет именно в доп.потоке.
Таймер или событие таймера?
А в чем проблема если он будет работать в основном потоке? Простите уж меня непонимающего!!!!
← →
Lamer6666 (2012-06-20 13:18) [43]
> Я такие задачи решаю написание обычной консольной программы
> (можно и не консольной, конечно, а обычной, с GUI, но смысла
> в тут GUI нет никакого). Эта программа делает все полезное
> (прочитать, отправить и т.д.).
> Через sheduler windows (который "назначенные задания" в
> русской виндовс называется) настраиваю запуск этой программы
> с нужной периодичностью. Все, никаких сервисов не нужно.
>
Тоже вариант, но нужна служба. Спасибо за вариант ))
← →
KSergey © (2012-06-20 14:01) [44]Всяким говном инет заполнен, а нормальной статьи про то, как устроены сервисы в виндах - нету...
А ведь когда-то я находил, когда сервис надо было состряпать, причем по-русски.
← →
Lamer6666 (2012-06-20 14:08) [45]
> Всяким говном инет заполнен, а нормальной статьи про то,
> как устроены сервисы в виндах - нету...
И о том же... ((((((((((
← →
KSergey © (2012-06-20 14:20) [46]> Lamer6666 (20.06.12 14:08) [45]
Но вы поищите.
Причем советую не про дельфи искать/читать. Организация работы сервиса - она ж от дельфи не зависит.
← →
Dennis I. Komarov © (2012-06-20 15:01) [47]
> Таймер или событие таймера?
>
> А в чем проблема если он будет работать в основном потоке?
> Простите уж меня непонимающего!!!!
Он не будет там работать, как его не "кидай на форму"... Да забудь ты про таймер.
И основной поток службы для управления ею. Не лезь туда с логикой. Создал там поток, и пусть он делает все что надо...
← →
Сергей М. © (2012-06-20 15:08) [48]
> Таймер или событие таймера?
Это два неразрывных понятия.
> в чем проблема если он будет работать в основном потоке?
Проблема, если ее и нет сейчас, обязательно будет когда юзер сперепугу-сбодуна или по незнанию отключит опцию взаимодействия твоего сервиса с рабочим столом.
Ограничить его в этом ты заведомо не сможешь, если у того админ.права, - и получишь ты в результате со своим оконным таймером в осн.потоке большущие граблищи.
← →
KSergey © (2012-06-20 15:18) [49]Ну вот же например пример сервиса именно на дельфи, где раз в заданное количество секунд тупо запускается нужный код.
http://www.tolderlund.eu/delphi/service/service.htm
Задержка на одну секунду тупо на Sleep. Достаточно подкрутить там интервал.
← →
Dennis I. Komarov © (2012-06-20 15:53) [50]
> KSergey © (20.06.12 15:18) [49]
Вешать логику в OnExecute без особой нужности - большая бяка.
← →
Lamer6666 (2012-06-20 16:26) [51]
> Ну вот же например пример сервиса именно на дельфи, где
> раз в заданное количество секунд тупо запускается нужный
> код.
> http://www.tolderlund.eu/delphi/service/service.htm
>
> Задержка на одну секунду тупо на Sleep. Достаточно подкрутить
> там интервал.
Урааа наконец то хоть что то.....
Огромное спасибо!!!
← →
Давайте будем жрать! (2012-06-20 16:28) [52]
> юзер сперепугу-сбодуна или по незнанию отключит опцию взаимодействия
> твоего сервиса с рабочим столом
Так в висте и выше эта фигня отключена вообще.
← →
Сергей М. © (2012-06-20 21:20) [53]
> Dennis I. Komarov © (20.06.12 15:53) [50]
По мне так большей "бякой" будет плодить доп.потоки "без особой нужности", с учетом того факта что система автоматически снабжает каждый стартующий сервис минимум одним доп.потоком, который совершенно бестолку простаивает в ожидании крайне редко адресуемых ему системой команд.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
Память: 0.6 MB
Время: 0.074 c