Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.61 MB
Время: 0.067 c
8-1227612031
axwork
2008-11-25 14:20
2013.03.22
Вопрос про раскодирование потока с IP камеры Axis (MJPEG)


2-1340011274
начинающий_
2012-06-18 13:21
2013.03.22
битовые операции


8-1228318270
exkalement
2008-12-03 18:31
2013.03.22
Визуализация?


15-1341404995
alexdn
2012-07-04 16:29
2013.03.22
Главное меню Joomla


2-1334682069
SiDimka
2012-04-17 21:01
2013.03.22
DBGrid > TreeView > DBGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский