Link to home
Start Free TrialLog in
Avatar of nitdgrev
nitdgrev

asked on

D5 NT Services & Thread messages

I have written an NT service in D5 which spawns multiple threads to perform various tasks and generally all works fine.  

The main problem I have is posting a message back to the main service thread when each spawned thread is finished (terminated).  The code snippet is  below.

In the Terminate Method of the Thread I have :

procedure TSapSMUHourThread.Terminate ;
begin
  PostThreadMessage(TheService.ServiceThread.ThreadID,wm_ThreadDoneMsg,Self.ThreadID,0) ;
  inherited Terminate ;
end ;

In the Main service I have const & message handler declared as :

.
const
  wm_ThreadDoneMsg = wm_User + 8 ;
.
.
.
procedure TService_CDMS_CS.ThreadDone(var AMessage : TMessage); message ;
.
.

I have debugged this and this message handler is definitely NOT activated.

Does anyone have any ideas ??

thanks in advance.
Avatar of rwilson032697
rwilson032697

Are you sure it isn't

procedure TService_CDMS_CS.ThreadDone(var AMessage : TMessage); message wm_ThreadDoneMsg;

in your code. If not, it should be!

Cheers,

Raymond.


Avatar of nitdgrev

ASKER

ooops!!! a typo!.

Yes it is as you suggest (note I should have TTheService instead of TService_CDMS_CS as well).  It should read :

procedure TTheService.ThreadDone(var AMessage : TMessage); message wm_ThreadDoneMsg;

I just failed to make the critical step or typing it out here! Sorry for the confusion.
Have you tried a different constant (like wm_user + 1234) in case the one you used has already been taken?

Cheers,

Raymond.
Might be a problem. I think Delphi is using itself some WM_USER + x Values for internal purposes. I know, that sounds really stupid, but I thought that's the way it is.

Try as rwilson said WM_USER + 1234...
I have tried using some other values but still can't get it to work.  I will try a few more combinations but it is looking grim.

Is this the correct procedure to use (ie PostThreadMessage) when sending a message back to the main service thread?
I have for the time being an alternative to using messages which is working fine.

Instead of creating a message I have written an OnTerminate event handler for the Thread in question.  As far as I can tell this will be invoked in much the same way as the ThreadDone message handler.  

(I would still like to get the messages working however).

Is your main service thread the same as the main VCL thread?

if so you could just use PostMessage...

Cheers,

Raymond.
This may, or may not, help:

PRB: PostThreadMessage Messages Lost When Posted to UI Thread
ID: Q183116

The information in this article applies to:

Microsoft Win32 Software Development Kit (SDK)


SYMPTOMS
Messages sent to a UI thread through PostThreadMessage are lost if the messages are posted while the user is manipulating a window owned by the thread. Messages might be lost if they are sent while the user moves or resizes the window or if the window is a modal dialog box.



CAUSE
When an UI thread is involved in modal behavior, the thread pumps messages in a message loop internal to the modal system rather than in the thread's main message loop. Messages that are posted to a window can still be dispatched to the window procedure of the target window, because the messages are associated with a window. However, thread messages need to be handled directly by the message loop, because they cannot be automatically dispatched elsewhere. Since the secondary message loop does not know about the thread message, it will be dropped.



RESOLUTION
Rather than using PostThreadMessage to post messages to a UI thread, use PostMessage to post messages to a window owned by that thread. Since messages directed to a window can be dispatched by a secondary message loop, the messages is still handled properly, even when the thread is not running in its primary message loop.

To use this method, the thread must create a window that lives throughout the period that it must receive messages, and the application sending the messages must have a handle to that window available.



STATUS
This behavior is by design.

Thanks Raymond for all your suggestions.

While so far I haven't managed to solve this problem you do deserve some points.

The article does seem to make sense but how does this apply to an NT Service as there is no modal window ?  In regards to your comment about the VCL thread, I am not really certain, as I only assumed there was just the main service thread, no VCL thread?  If they are one & the same what handle do you use with PostMessage?  Am I on the right track do you think?



I see now. Yes, your main service thread will be the main VCL thread.

PostThreadMessage will fail if there is no messages loop for the thread you are sending the message to. Can you see if it fails or not?

Read the help for PostThreadMessage, it has some more information regarding handling situations where the thread does not have a message loop.

Cheers,

Raymond.
ASKER CERTIFIED SOLUTION
Avatar of aldyn
aldyn

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Aldyn and rwilson.  This has rectified the problem.  Note all help has been appreciated.