Solved

D5 NT Services & Thread messages

Posted on 2000-03-08
12
309 Views
Last Modified: 2012-05-04
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.
0
Comment
Question by:nitdgrev
12 Comments
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2599406
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.


0
 

Author Comment

by:nitdgrev
ID: 2599428
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.
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2599482
Have you tried a different constant (like wm_user + 1234) in case the one you used has already been taken?

Cheers,

Raymond.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Expert Comment

by:brunohe
ID: 2600486
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...
0
 

Author Comment

by:nitdgrev
ID: 2602487
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?
0
 

Author Comment

by:nitdgrev
ID: 2602590
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).

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2602716
Is your main service thread the same as the main VCL thread?

if so you could just use PostMessage...

Cheers,

Raymond.
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2603864
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.

0
 

Author Comment

by:nitdgrev
ID: 2606683
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?



0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2606794
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.
0
 
LVL 1

Accepted Solution

by:
aldyn earned 300 total points
ID: 2607669
Your problem is caused by manner in which service thread processes messages. Look into svcmgr unit and search for PeekMessage calls (there are two only). Look on the second one. It takes messages from the thread's message queue and processes it. Note that if the hwnd parameter is 0 (it is your case because you send message to thread, not to window) then this messages will be processes in special manner. Namely it will be treated as a service control message. In your case it will result to DoCustomControl call with one parameter only. Other information from your message will be lost. The solution is simple enough: you will have to create a window (look how TTimer component creates window to receive WM_TIMER for example, you can use the same code with minimum changes)
and then you will be able to send messages to it. Let me know if you need a ready-to-use code.
0
 

Author Comment

by:nitdgrev
ID: 2610272
Thanks Aldyn and rwilson.  This has rectified the problem.  Note all help has been appreciated.
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question