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

Вниз

Прощу помощи разобраться со службой.   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.09 c
2-1331284249
rraktir
2012-03-09 13:10
2013.03.22
Как сделать маску ввода под проценты?


2-1333098565
leklerk
2012-03-30 13:09
2013.03.22
Fields Editor в ADODataSet


15-1334225125
REAn
2012-04-12 14:05
2013.03.22
Компиляция BPL


2-1337760388
yuiyui
2012-05-23 12:06
2013.03.22
ctrl + i не работает


15-1345453966
Es
2012-08-20 13:12
2013.03.22
ADO + большая транзакция