Главная страница
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?



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

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

Наверх




Память: 0.58 MB
Время: 0.053 c
15-1353616205
Юрий
2012-11-23 00:30
2013.03.22
С днем рождения ! 23 ноября 2012 пятница


15-1343319699
alexdn
2012-07-26 20:21
2013.03.22
php, цвет ссылки


15-1341094198
COMMODORE-128
2012-07-01 02:09
2013.03.22
Прием символов по СОМ


2-1347121511
alexdn
2012-09-08 20:25
2013.03.22
Верт скролл бар для формы


2-1329837414
Чайник
2012-02-21 19:16
2013.03.22
Управление z-order окон