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



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

Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.074 c
2-1340780940
aka
2012-06-27 11:09
2013.03.22
Удаления пробелов в строке.


2-1348400327
Jimmy
2012-09-23 15:38
2013.03.22
Изменение курсора мыши


4-1262850914
Dy1
2010-01-07 10:55
2013.03.22
получение html-страницы post-запросом


2-1329302821
LDV
2012-02-15 14:47
2013.03.22
добавление/удаление в/из TList


15-1337866798
Cobalt
2012-05-24 17:39
2013.03.22
Разноцветный многострочный хинт





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский