I have implemented a windows xp service application that starts a couple of working threads. From one of the threads i need to send custom messages back to the service. How do i do that?
One option is to use OmniThreadLibrary (read this blog post for an example).
I agree with TOndrej that shared objects should be sufficient.
On the other hand you can use my IPC (Cromis IPC) which works just fine inside services. It is easy to use, message oriented, so you don't need to know how named pipes work and very fast. The server part also uses a thread pool, so there is no waiting for something to be processed. You can use the fire and forget scenario.
Or if you think a little redesign is ok, you can try OmniThreadLibrary which has all the messaging already build in and is made for tasks like this.
EDIT:
Ok probably the cleanest way to go, without any redesing is to have a common object list which is protected by a critical section. The working thread is adding objects that need to be processed in the list. When and object is added the working thread signals an event. Then you have an object processing thread which is waiting with WaitForSingleObject for this event. As soon as something is added to the list the event is signaled and the processing thread just processes all the objects it finds in the list. Then it waits again. All you need to do is to protect the access to the common list.
Simplified the code would look like this:
WORKER THREAD
ObjectList.Add(MessageObject);
SetEvent(FEvent);
PROCESSING THREAD
while not Terminated do
begin
WaitForSingleObjest(FEvent, INFINITE);
// process all the objects
end;
Creating message-only window:
procedure TMyService.MessageQueueDispatch(var Message: TMessage);
begin
Dispatch(Message); //Delphi default dispatcher for TMyService
end;
procedure TMyService.SomeKindOfOnCreate;
begin
MessageQueue := AllocateHWnd(MessageQueueDispatch);
end;
Destroying:
procedure TMyService.SomeKindOfDestroy;
begin
CloseHandle(MessageQueue);
end;
Now you can handle messages like you would do with form messages:
TMyService = class(TService)
...
protected
procedure HandleMyMessage(var msg: TMsg); message WM_MY_MESSAGE;
end;
Delphi Dispatch() handler will take care of calling the function.
Thanks for your help. Here is how I solved the problem:
In the Service class definition:
...
WHandle: HWND;
protected
procedure HandleServiceMessage(var Msg: TMessage); virtual;
...
In the ServiceExecute method:
...
WHandle := AllocateHWnd(HandleServiceMessage);
MyThread := TMyThread.Create(true);
MyThread.HndMain := WHandle;
MyThread.Resume;
while not Terminated do ServiceThread.ProcessRequests(True);
DeallocateHWnd(WHandle);
end;
In ServiceStop method:
...
MyThread.Terminate;
...
And the method for handling messages:
procedure TMessageService.HandleServiceMessage(var Msg : TMessage);
var
Handled: Boolean;
begin
Handled := True;
if Msg.Msg = WM_MYMESSAGE
then
Beep;
else
Handled := False;
end;
if Handled then
Msg.Result := 0
else
Msg.Result := DefWindowProc(WHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;
In MyThread.Execute method:
...
PostMessage(HndMain,WM_MYMESSAGE,0,0);
...
Its working just fine.