TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 14:05
Оценка:
Подскажите пожалуйста верно ли копаю.
Идея следующая.
Нужен некий сервис, к нему подключаются плагины (DLL некие). Эти DLL должны отслеживать изменения в БД (эвенты от IB/FB) и посылать письма.
Итого. Мне необходимо создать сервис-приложение. На старт сервиса повесить как то регистрацию плагина, т.е. это я так понимаю некий поток в котором должна работать DLL. Смысл в том, что по большому счету сам сервис ничего не делает, он должен просто управлять плагином — запустить поток и при останове сервиса остановить его. Сама DLL может быть какой угодно, т.е. хоть по таймеру вызывать формы диалога.
Подскажите, или если есть, костяк всего этого. А то общую картину вижу, а по частям как-то не складывается. Т.е. как к примеру запустить в потоке DLL, и верно ли вот это?
procedure TService1.ServiceExecute(Sender: TService);
begin
while not Terminated do begin
ServiceThread.ProcessRequests(false);
end;
end;
Или все же тут должна быть некая обработка?
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 15:27
Оценка: 2 (1)
Здравствуйте, Strannic, Вы писали:

S>Подскажите пожалуйста верно ли копаю.

S>Идея следующая.
S>Нужен некий сервис, к нему подключаются плагины (DLL некие). Эти DLL должны отслеживать изменения в БД (эвенты от IB/FB) и посылать письма.
S>Итого. Мне необходимо создать сервис-приложение. На старт сервиса повесить как то регистрацию плагина, т.е. это я так понимаю некий поток в котором должна работать DLL. Смысл в том, что по большому счету сам сервис ничего не делает, он должен просто управлять плагином — запустить поток и при останове сервиса остановить его. Сама DLL может быть какой угодно, т.е. хоть по таймеру вызывать формы диалога.
S>Подскажите, или если есть, костяк всего этого. А то общую картину вижу, а по частям как-то не складывается. Т.е. как к примеру запустить в потоке DLL, и верно ли вот это?
S>procedure TService1.ServiceExecute(Sender: TService);
S>begin
S> while not Terminated do begin
S> ServiceThread.ProcessRequests(false);
S> end;
S>end;
S>Или все же тут должна быть некая обработка?

1. Не используй событие ServiceExecute. Обязательно вытри.
2. Повесь свой код на ServiceStart — запусти свой поток(и)
3. ServiceStop — останови поток(и)
Re[2]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 16:00
Оценка:
Здравствуйте, Danchik, Вы писали:
D>1. Не используй событие ServiceExecute. Обязательно вытри.
D>2. Повесь свой код на ServiceStart — запусти свой поток(и)
D>3. ServiceStop — останови поток(и)

Ясно.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 16:47
Оценка:
При попытке запуска службы, в случае если она использует функцию из DLL, происходит вылет по ошибке 1053.
Функция уже упрощена до минимума — выводит месадж_бокс.
Если же повесить вызов функции на крейт сервиса и запустить сервис как приложение, то все работает как надо, но если попробывать ег стартовать, то выдает ошибку и не стартует.
Может быть нельзя использовать функции DLL в сервисах??? Бред. Если можно, то какие особенности их вызова?
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[2]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 17:18
Оценка: 2 (1)
Здравствуйте, Strannic, Вы писали:

S>При попытке запуска службы, в случае если она использует функцию из DLL, происходит вылет по ошибке 1053.

1053 — Старт занимает слишком много времени

S>Функция уже упрощена до минимума — выводит месадж_бокс.

Месадж бокс в сервисе выводить нельзя (читай не рекомендуется, трудно), особенно делфовский. Для этого нужно играться с интерактивными сервисами.
Да и если ты месадж бокс выдаш 1053 тебе обеспечен.

S>Если же повесить вызов функции на крейт сервиса и запустить сервис как приложение, то все работает как надо, но если попробывать ег стартовать, то выдает ошибку и не стартует.

Случайно COM не используеш?

S>Может быть нельзя использовать функции DLL в сервисах??? Бред. Если можно, то какие особенности их вызова?

Можна, только есть ограничения на использование, например с GUI (правда и это обходится, но не так просто)
Re[3]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 17:25
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Месадж бокс в сервисе выводить нельзя (читай не рекомендуется, трудно), особенно делфовский. Для этого нужно играться с интерактивными сервисами.

D>Да и если ты месадж бокс выдаш 1053 тебе обеспечен.
Как ни странно, но щас щапустил — все работает, даже при них. Причина была бональна — не находил DLL, так как она была включена в шифрованную папку.


S>>Может быть нельзя использовать функции DLL в сервисах??? Бред. Если можно, то какие особенности их вызова?

D>Можна, только есть ограничения на использование, например с GUI (правда и это обходится, но не так просто)

Проблема щас в другом, точнее не проблема а непонятнка. Стартует поток Thread.Execute; но как только Execute выполнилось поток тут же вызывает DoTerminate. В итоге я не сильно соображаю, каким образом не завершать работу потока пока ему явно не придет на это команды??? Ну не делать же в Execute Repeat Until Terminated; — так же все ресурсы можно посадить!
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[3]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 17:32
Оценка:
Т.е. картина проста — мне необходимо, что бы поток запустивший ДЛЛ (в ней находится DataModule, на котором уже может висеть и отправка писем и проверка эвентов из базы и прочее) не закрывался сам по себе. В ДЛЛ я просто пишу
procedure StartPluggin;
begin
  dmNSTL := TdmNSTL.Create(nil);
end;

procedure StopPluggin;
begin
  dmNSTL.Free;
end;

И ожидаю, что пока не будет вызван StopPluggin; форма будет висеть в памяти.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[4]: TService, TServiceThread, DLL
От: wellwell Австралия https://www.softperfect.com
Дата: 23.05.05 18:10
Оценка:
"Strannic" <10509@users.rsdn.ru> wrote in message news:1187099@news.rsdn.ru...
>Ну не делать же в Execute Repeat Until Terminated; — так же все ресурсы можно посадить!

делать
repeat
sleep(100) (или Sleep(0))
until terminated;
Posted via RSDN NNTP Server 1.9
Re[5]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 18:19
Оценка:
?!?!?
Удевлен. Но однако все равно что-то не так с этой ДЛЛ потоке...
procedure TDllThread.Execute;
Const DLL = 'C:\Work\Service\DLL\NSTL\bNSTL.dll';
begin
  HandleDLL := LoadLibrary(DLL);
  if HandleDLL <> 0 then
  begin
    @StartPluggin := GetProcAddress(HandleDLL, 'StartPluggin');
    @StopPluggin := GetProcAddress(HandleDLL, 'StopPluggin');
    if( (@StartPluggin = nil)or(@StopPluggin = nil) )then begin
      MessageDlg('Плагин '+DLL+ ' не соответствует требуемому.',mtInformation,[mbOk],0);
      Exit;
    end;
    StartPluggin;
  end
   else
     MessageDlg('Не найден указанный плагин - '+DLL,mtError,[mbOk],0);
MessageDlg('1',mtInformation,[mbOk],0); -- первый месадж
  repeat
   sleep(100);
  until terminated;
MessageDlg('2',mtInformation,[mbOk],0); -- второй месадж
end;

В DLL на DataModule лежит таймер, и он бипает каждую секунду. Так вот когда вызываеться месадж 1 — он бибает. после его закрытия тишина. причем сервис закрыть не удаеться — очень долго висит в ожидани, после чего я его снимаю ручками. да 2-го месаджа так и не добирается.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[4]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 18:23
Оценка: 2 (1)
Здравствуйте, Strannic, Вы писали:

S>Проблема щас в другом, точнее не проблема а непонятнка. Стартует поток Thread.Execute; но как только Execute выполнилось поток тут же вызывает DoTerminate. В итоге я не сильно соображаю, каким образом не завершать работу потока пока ему явно не придет на это команды??? Ну не делать же в Execute Repeat Until Terminated; — так же все ресурсы можно посадить!


Тут тебе необходимо в потоке организовать очередь сообщений.
Можно сделать ее самым банальным способом — создать в потоке окно и посылать к нему сообщения с помощью функций SendMessage (дождаться результата) и PostMessage (поставить сообщение в очередь и продолдать работать)

Создать окно AllocateHWnd и уничтожить DeallocateHWnd (юнит Forms.pas)

Твой поток будет выглядеть так:


const
  MY_MESSAGE_BASE = CM_BASE + 1000;
  MY_MESSAGE1 = MY_MESSAGE_BASE + 1; // sample message 1
  MY_MESSAGE2 = MY_MESSAGE_BASE + 2; // sample message 2

type
  TPluginThread = class (TThread)
  private
    FWndHandle: HWND;
  protected
    procedure WndProc(var Message: TMessage); virtual;
    procedure Execute; override;
    procedure Idle;
    function ProcessMessage(var Msg: TMsg): Boolean;
    procedure ProcessMessages;
  private
    procedure MyMessage1(var Message: TMessage); message MY_MESSAGE1;
    procedure MyMessage2(var Message: TMessage); message MY_MESSAGE2;
  public
    property WndHandle: HWND read FWndHandle;
  end;


implementation

procedure TPluginThread.Execute;
begin
  try
    FWndHandle := AllocateHWND (WndProc);
    try
      ProcessMessages;
    finally
      DeallocateHWnd (FWndHandle);
    end;
  except
   // kill any exceptions
  end;
end;

procedure TPluginThread.ProcessMessages;
var
  Msg: TMsg;
begin
  while not Terminated and ProcessMessage (Msg) do {loop};
end;

function TPluginThread.ProcessMessage(var Msg: TMsg): Boolean;
begin
  Result := False;

  if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
  begin
    if GetMessage (Msg, 0, 0, 0) then begin
      Result := True;
      if Msg.Message <> WM_QUIT then begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end else
        Terminate;
    end;
  end else
    WaitMessage;

  Idle;

end;

procedure TPluginThread.Idle;
begin
  { do something if you want}
end;


procedure TPluginThread.WndProc(var Message: TMessage);
begin
  try
    Dispatch(Message);
  except
    // kill exceptions;
  end;
end;

procedure TPluginThread.MyMessage1(var Message: TMessage);
begin
  // do something
end;

procedure TPluginThread.MyMessage2(var Message: TMessage);
begin
  // do something
end;


Пример посылки сообщения:
 SendMessage (MyThread.WndHandle, MY_MESSAGE1, 0, 0)
Re[6]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 18:36
Оценка:
Здравствуйте, Strannic, Вы писали:

S>?!?!?

S>Удевлен. Но однако все равно что-то не так с этой ДЛЛ потоке...

Sleep позволяет отдать время твоего потока Windows, что предотвратит перегрузку процессора. Лично я не люблю такой подход к написанию потоков — как
то не чисто выглялит. Есть такое понятие Event — вот это вариант когда необходимо продолжать работать, а не крутится на месте пока какой то флажок не поставят.

S>
S>procedure TDllThread.Execute;
S>Const DLL = 'C:\Work\Service\DLL\NSTL\bNSTL.dll';
S>begin
S>  HandleDLL := LoadLibrary(DLL);
S>  if HandleDLL <> 0 then
S>  begin
S>    @StartPluggin := GetProcAddress(HandleDLL, 'StartPluggin');
S>    @StopPluggin := GetProcAddress(HandleDLL, 'StopPluggin');
S>    if( (@StartPluggin = nil)or(@StopPluggin = nil) )then begin
S>      MessageDlg('Плагин '+DLL+ ' не соответствует требуемому.',mtInformation,[mbOk],0);
S>      Exit;
S>    end;
S>    StartPluggin;
S>  end
S>   else
S>     MessageDlg('Не найден указанный плагин - '+DLL,mtError,[mbOk],0);
S>MessageDlg('1',mtInformation,[mbOk],0); -- первый месадж
S>  repeat
S>   sleep(100);
S>  until terminated;
S>MessageDlg('2',mtInformation,[mbOk],0); -- второй месадж
S>end;
S>

S>В DLL на DataModule лежит таймер, и он бипает каждую секунду. Так вот когда вызываеться месадж 1 — он бибает. после его закрытия тишина. причем сервис закрыть не удаеться — очень долго висит в ожидани, после чего я его снимаю ручками. да 2-го месаджа так и не добирается.

Ты на ServiceStop вызывал MyThread.Terminate?

Да и черт побери , перестань вызывать MessageDlg — это может тебе подвесить сервис. VCL не thread-safe. Если тебе уж так необходимо мессадж боксы видеть — вызывай MessageBox из Windows.pas
Re[5]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 18:50
Оценка:
Не сочтите совсем за деревянного, но что-то в этой жизни я безвозвратно упустил....
Бипы в ДЛЛ, а как я понимаю и выполнение ее, идут лишь в случае если повесить после запуска потока месадж. Т.е. пока висит месадж плагин крутиться, и как бы работает, но как только я его закрою — все — обработка его завершается. Почему??? Т.е. ДЛЛ работает пока явно держать систему на диалоге? Понимаю, что не так, а в чем тогда дело?
Даже если я просто вешал пустой цикл после вызова функции из ДЛЛ, то работа с этой ДЛЛ (бипы по таймеру) прекращалась.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[6]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 19:01
Оценка:
Здравствуйте, Strannic, Вы писали:

S>Не сочтите совсем за деревянного, но что-то в этой жизни я безвозвратно упустил....

S>Бипы в ДЛЛ, а как я понимаю и выполнение ее, идут лишь в случае если повесить после запуска потока месадж. Т.е. пока висит месадж плагин крутиться, и как бы работает, но как только я его закрою — все — обработка его завершается. Почему??? Т.е. ДЛЛ работает пока явно держать систему на диалоге? Понимаю, что не так, а в чем тогда дело?
S>Даже если я просто вешал пустой цикл после вызова функции из ДЛЛ, то работа с этой ДЛЛ (бипы по таймеру) прекращалась.

Поток заканчивает свою работу после того как выходит из метода Execute — надеюсь это понятно.

Возьми класс который я тебе написал перед этим.
Сделай так:

procedure TPluginThread.MyMessage1(var Message: TMessage);
begin
  StartPlugin
end;

procedure TPluginThread.MyMessage2(var Message: TMessage);
begin
  StopPlugin;
  Terminate;
end;


{На старте сервиса}
.......

  FMyThread := TPluginThread.Create (True);
  FMyThread.Resume;

  PostMessage (MyThread.WndHandle, MY_MESSAGE1, 0, 0);

....

{На остановке сервиса}

  if FMyThread <> nil then 
    SendMessage (MyThread.WndHandle, MY_MESSAGE2, 0, 0); { дождаться завершения }
Re[7]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 19:23
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Ты на ServiceStop вызывал MyThread.Terminate?

Да.

D>Да и черт побери , перестань вызывать MessageDlg — это может тебе подвесить сервис. VCL не thread-safe. Если тебе уж так необходимо мессадж боксы видеть — вызывай MessageBox из Windows.pas


Да это типа для отладки — не более.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[7]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 19:25
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Поток заканчивает свою работу после того как выходит из метода Execute — надеюсь это понятно.


Вот это как раз понятно.

D>Возьми класс который я тебе написал перед этим.

D>Сделай так:

Все сделал. В итоге не получаю вызова MyMessage1 — проверял бипами.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[8]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 19:31
Оценка:
S>Все сделал. В итоге не получаю вызова MyMessage1 — проверял бипами.

MyMessage2 — тоже не приходит
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[8]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 23.05.05 19:51
Оценка:
procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
DllThread := TDllThread.Create(false);
PostMessage (DllThread.WndHandle, MY_MESSAGE1, 0, 0);

Started := True;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
if DllThread <> nil then
SendMessage (DllThread.WndHandle, MY_MESSAGE2, 0, 0);

Stopped := True;
end;

Однако месаджы не проходят.
Причем после
DllThread := TDllThread.Create(false);
DllThread.WndHandle = 0
естественно месадж не попадает
PostMessage (DllThread.WndHandle, MY_MESSAGE1, 0, 0);
Однако "0" почему пока не ясно
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[9]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 20:33
Оценка: 3 (1)
Здравствуйте, Strannic, Вы писали:

S>procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);

S>begin
S> DllThread := TDllThread.Create(false);
S> PostMessage (DllThread.WndHandle, MY_MESSAGE1, 0, 0);

S> Started := True;

S>end;

S>procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);

S>begin
S> if DllThread <> nil then
S> SendMessage (DllThread.WndHandle, MY_MESSAGE2, 0, 0);

S> Stopped := True;

S>end;

S>Однако месаджы не проходят.

S>Причем после
S> DllThread := TDllThread.Create(false);
S>DllThread.WndHandle = 0
S>естественно месадж не попадает
S> PostMessage (DllThread.WndHandle, MY_MESSAGE1, 0, 0);
S>Однако "0" почему пока не ясно

Упс.
Тут проблема в том что окно еще не создалось.
пропробуй


  DllThread := TDllThread.Create(false);
  DllThread.WndHandle = 0;
  while DllThread.WndHandle = 0 do
    Sleep (0);
  PostMessage (DllThread.WndHandle, MY_MESSAGE1, 0, 0);


И иеще протрассируй создалось ли окно в методе Execute
Re[8]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 23.05.05 20:34
Оценка:
Здравствуйте, Strannic, Вы писали:

S>Здравствуйте, Danchik, Вы писали:


D>>Ты на ServiceStop вызывал MyThread.Terminate?

S>Да.

D>>Да и черт побери , перестань вызывать MessageDlg — это может тебе подвесить сервис. VCL не thread-safe. Если тебе уж так необходимо мессадж боксы видеть — вызывай MessageBox из Windows.pas


S>Да это типа для отладки — не более.

Вот именно эта отладка может тебе все испортить и ты не поймеш в чем дело. Пиши лучше в файл
Re[5]: TService, TServiceThread, DLL
От: Sinclair Россия https://github.com/evilguest/
Дата: 24.05.05 03:27
Оценка:
Здравствуйте, Danchik, Вы писали:
D>Можно сделать ее самым банальным способом — создать в потоке окно и посылать к нему сообщения с помощью функций SendMessage (дождаться результата) и PostMessage (поставить сообщение в очередь и продолдать работать)

D>Создать окно AllocateHWnd и уничтожить DeallocateHWnd (юнит Forms.pas)

Совершенно необязательно. Можно пользоваться PostThreadMessage и не думать, в какой оконной станции создается окно.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 24.05.05 07:22
Оценка:
D>И иеще протрассируй создалось ли окно в методе Execute

Сделал как ты написал. Окно создаеться хендл принимает значение, но месадж все равно не приходит.
Но вопрос мне кажеться еще в следующем: даже если я делал просто цикл в конце Execute, то ДЛЛ перестает работать (на ней как я уже писал есть Beep на таймере). Т.е. может быть в принципе такая идея не работоспособна?
И по ходу вопрос:
по условию задачи (но это худший вариант) я могу писать для каждого свой сервис, вместо плагина к сервису. Но... что лучше? или они одинаковы по затратам машинного времени и загрузкам процессора? или все же один сервис с десятком плагинов работающих в потоке лучше чем десяток сервисов?
З.Ы.: М-да — не выходит каменный цветок.
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[6]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 24.05.05 10:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Danchik, Вы писали:

D>>Можно сделать ее самым банальным способом — создать в потоке окно и посылать к нему сообщения с помощью функций SendMessage (дождаться результата) и PostMessage (поставить сообщение в очередь и продолдать работать)

D>>Создать окно AllocateHWnd и уничтожить DeallocateHWnd (юнит Forms.pas)

S>Совершенно необязательно. Можно пользоваться PostThreadMessage и не думать, в какой оконной станции создается окно.

Так то оно так, только вот SendThreadMessage нету . Необходимо как то синхронизироваться.
Re[11]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 24.05.05 10:55
Оценка:
Здравствуйте, Strannic, Вы писали:

D>>И иеще протрассируй создалось ли окно в методе Execute


S>Сделал как ты написал. Окно создаеться хендл принимает значение, но месадж все равно не приходит.


Странненько... Проверь попадает ли в WndProc метод.

S>Но вопрос мне кажеться еще в следующем: даже если я делал просто цикл в конце Execute, то ДЛЛ перестает работать (на ней как я уже писал есть Beep на таймере). Т.е. может быть в принципе такая идея не работоспособна?


Кажется я таки понял в чем твоя проблема. Timer — это те же Windows сообщения, соответственно их нужно обрабатывать, и причем в том же потоке где Timer был создан. Так как предложенный мною поток имеет реализацию обработки сообщений — то тебе абсолютно ничего не надо дописывать. Но одно но — создавать все Модули и стартовать плагины нужно именно в Execute. Конструктор Create потока для этих целей не подходит.

S>И по ходу вопрос:

S>по условию задачи (но это худший вариант) я могу писать для каждого свой сервис, вместо плагина к сервису. Но... что лучше? или они одинаковы по затратам машинного времени и загрузкам процессора? или все же один сервис с десятком плагинов работающих в потоке лучше чем десяток сервисов?
S>З.Ы.: М-да — не выходит каменный цветок.

Думаю что все таки один сервис лучше Не будеш же ты из-за каждого плагина регистрить новый сервис
Re[12]: TService, TServiceThread, DLL
От: Strannic Россия www.new-point.ru
Дата: 24.05.05 11:30
Оценка:
D>Странненько... Проверь попадает ли в WndProc метод.

Да попадает.

D>Кажется я таки понял в чем твоя проблема. Timer — это те же Windows сообщения, соответственно их нужно обрабатывать, и причем в том же потоке где Timer был создан. Так как предложенный мною поток имеет реализацию обработки сообщений — то тебе абсолютно ничего не надо дописывать. Но одно но — создавать все Модули и стартовать плагины нужно именно в Execute. Конструктор Create потока для этих целей не подходит.


Т.е. мне необходимо иметь клас плагина, коий нужно экспортировать из DLL, причем незнаю как, и который создавать на Execute потока, а уже реализацию создания этого класса можно(нужно) делать в самой DLL плагина. Верно я понял? Или может лучше в этом случае плагины писать как потоки, но каждый плагин это один поток. Т.е. реализацию DLL делать как поток? А по событию останова сервиса вызывать функцию DLL, которая будет глушить этот поток.

Еще. А нужнен ли TDllThread.MyMessage2, ведь как только Execute отработает автматом будет вызван TDllThread.DoTerminate, может более коректно на нем производить остановку и выгрузку DLL, т.е. вместо

procedure TDllThread.MyMessage2(var Message: TMessage);
begin
  if HandleDLL <> 0 then StopPluggin;
  Terminate;
  FreeLibrary(HandleDLL);
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  if DllThread <> nil then
    SendMessage (DllThread.WndHandle, MY_MESSAGE2, 0, 0);
  Stopped := True;
end;

сделать просто
procedure TDllThread.DoTerminate;
begin
  if HandleDLL <> 0 then StopPluggin;
  FreeLibrary(HandleDLL);
end;

что скажешь?

D>Думаю что все таки один сервис лучше Не будеш же ты из-за каждого плагина регистрить новый сервис


Поэтому и хотел смотреть в сторону плагинов к сервису. А что касаеться производительности там, загрузки проца и прочее, я понимаю, что щас это не критично, но все же? Так — что называеться для в общеобразовательных целях?
Любая проблема проектирования может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев.
Re[13]: TService, TServiceThread, DLL
От: Danchik Украина  
Дата: 24.05.05 12:09
Оценка:
Здравствуйте, Strannic, Вы писали:

D>>Странненько... Проверь попадает ли в WndProc метод.


S>Да попадает.


D>>Кажется я таки понял в чем твоя проблема. Timer — это те же Windows сообщения, соответственно их нужно обрабатывать, и причем в том же потоке где Timer был создан. Так как предложенный мною поток имеет реализацию обработки сообщений — то тебе абсолютно ничего не надо дописывать. Но одно но — создавать все Модули и стартовать плагины нужно именно в Execute. Конструктор Create потока для этих целей не подходит.


S>Т.е. мне необходимо иметь клас плагина, коий нужно экспортировать из DLL, причем незнаю как, и который создавать на Execute потока, а уже реализацию создания этого класса можно(нужно) делать в самой DLL плагина. Верно я понял?

Я бы тебе советовал сделать плагины COM in-proс серверами. Правда это нужно долго обьяснять
Можна также сделать конструкцию типа:

PluginHandle : Integer;
...
PluginHandle := {MyDll}CreatePlugin;
...
{MyDll}StartPlugin (PluginHandle)
..
{MyDll}StopPlugin (PluginHandle)



S>Или может лучше в этом случае плагины писать как потоки, но каждый плагин это один поток. Т.е. реализацию DLL делать как поток? А по событию останова сервиса вызывать функцию DLL, которая будет глушить этот поток.


Думаю не стоит писать полагины потоками, но тоже вариант, иногда это необходимо


S>Еще. А нужнен ли TDllThread.MyMessage2, ведь как только Execute отработает автоматом будет вызван TDllThread.DoTerminate, может более коректно на нем производить остановку и выгрузку DLL, т.е. вместо


S>
S>procedure TDllThread.MyMessage2(var Message: TMessage);
S>begin
S>  if HandleDLL <> 0 then StopPluggin;
S>  Terminate;
S>  FreeLibrary(HandleDLL);
S>end;

S>procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
S>begin
S>  if DllThread <> nil then
S>    SendMessage (DllThread.WndHandle, MY_MESSAGE2, 0, 0);
S>  Stopped := True;
S>end;
S>

S>сделать просто
S>
S>procedure TDllThread.DoTerminate;
S>begin
S>  if HandleDLL <> 0 then StopPluggin;
S>  FreeLibrary(HandleDLL);
S>end;
S>

S>что скажешь?

DoTerminate вызывается в главном потоке приложения — это невсегда корректно, да и может подвесить всю программу если StopPlugin зависнет.
Первый вариант более предпочтительней.

D>>Думаю что все таки один сервис лучше Не будеш же ты из-за каждого плагина регистрить новый сервис


S>Поэтому и хотел смотреть в сторону плагинов к сервису. А что касаеться производительности там, загрузки проца и прочее, я понимаю, что щас это не критично, но все же? Так — что называеться для в общеобразовательных целях?


Советую тебе сделать тестовую программу с двумя кнопками Start (like ServiceStart) и Stop (like ServiceStop).
На ней ты сможеш протестить как все работает в дебаге (это проще чем дебажить сервис).

А потом код перенеси на сервис. Если не будет работать можна проанализировать что у тебя с Permission и другой функциональностью, которая некорректно работает в сервисе.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.