Solved

How to send message from thread to main thread?

Posted on 2006-07-10
5
1,158 Views
Last Modified: 2012-06-21
I have created a windows service that spawns a new thread. I need to send messages to the service(main thread) as this child thread is executing. Everything I have found so far seems to rely on a GUI application. I have no user interface, I just need to update a string variable in the main thread based on what the spawned thread is doing.
0
Comment
Question by:seinc
5 Comments
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17077396

Below is an example of a worker thread that updates the sample service at random intervals (displays a service dialog, which requires interactive  = true). This should give you some ideas of what you can do. If have questions, then please ask, but it would helpe to see specific code examples for what you are currently doing.

Regards,
Russell

---


unit SampleService;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;

type
  TWorkerThread     =  class(TThread)
  private
     // Private declarations
     procedure      UpdateService;
  protected
     // Protected declarations
     procedure      Execute; override;
  public
     // Public declarations
     constructor    Create;
  end;

type
  TsvcSample        =  class(TService)
     procedure      ServiceStart(Sender: TService; var Started: Boolean);
     procedure      ServicePause(Sender: TService; var Paused: Boolean);
     procedure      ServiceContinue(Sender: TService; var Continued: Boolean);
     procedure      ServiceStop(Sender: TService; var Stopped: Boolean);
  private
     // Private declarations
     FWorker:       TWorkerThread;
  protected
     // Protected declarations
     procedure      UpdateServiceState(Value: String);
  public
     // Public declarations
     function       GetServiceController: TServiceController; override;
  end;

var
  svcSample:        TsvcSample;

implementation
{$R *.DFM}

//// TWorkerThread /////////////////////////////////////////////////////////////
procedure TWorkerThread.UpdateService;
begin

  // Running in context of main thread
  svcSample.UpdateServiceState(IntToStr(GetTickCount));

end;

procedure TWorkerThread.Execute;
begin

  // While not terminated
  while not(Terminated) do
  begin
     // Sleep a random amount of time
     Sleep(Random(5000));
     // Update the service
     Synchronize(UpdateService);
  end;

end;

constructor TWorkerThread.Create;
begin

  // Set defaults
  FreeOnTerminate:=False;
  Priority:=tpLower;

  // Perform inherited
  inherited Create(False);

end;

//// TsvcSample ////////////////////////////////////////////////////////////////
procedure ServiceController(CtrlCode: DWord); stdcall;
begin

  // Handle the control code
  svcSample.Controller(CtrlCode);

end;

function TsvcSample.GetServiceController: TServiceController;
begin

  // Return the service controller
  Result:=ServiceController;

end;

procedure TsvcSample.ServiceStart(Sender: TService; var Started: Boolean);
begin

  // Create the worker thread
  FWorker:=TWorkerThread.Create;

end;

procedure TsvcSample.ServicePause(Sender: TService; var Paused: Boolean);
begin

  // Pause the worker thread
  FWorker.Suspend;

end;

procedure TsvcSample.ServiceContinue(Sender: TService; var Continued: Boolean);
begin

  // Resource protection
  try
     // Resume the worker thread
     FWorker.Resume;
  finally
     // Continue the service
     Continued:=True;
  end;

end;

procedure TsvcSample.ServiceStop(Sender: TService; var Stopped: Boolean);
begin

  // Resource protection
  try
     // Terminate the thread
     FWorker.Terminate;
     // Wait for thread execute to finish
     FWorker.WaitFor;
  finally
     // Free worker thread
     FWorker.Free;
  end;

end;

procedure TsvcSample.UpdateServiceState(Value: String);
begin

  // Update from worker thread
  MessageBox(0, PChar(Value), 'Worker Update', MB_OK or MB_SERVICE_NOTIFICATION);

end;

end.
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17077569
Unfortunately, the very nature of the servicethread does not easily do as you request.
The main service thread does very little after it starts things.
You can use ControlService() and "DoCustomControl" but it's not ideal.
I'd recommend you use some other form of inter process communication
sockets, shared memory, named pipes etc.
0
 
LVL 17

Accepted Solution

by:
TheRealLoki earned 500 total points
ID: 17077578
since you just want to update a variable, you could use a TCriticalSection
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 17097597
I agree with TheRealLoki. If you only need to update a string, use a critical section.

Or you use a Windows event with the CreateEvent/PulseEvent/SetEvent/ResetEvent API functions. But that would mean your main thread is continuously waiting for some event.

Or you implement your own messageloop and thus you would be able to send/post messages to your main thread.

But basically there are many different solutions. Just keep in mind that whenever you have one thread sending messages to the other thread, the other thread must be able to receive and respond to this message. This often means that the main thread has to regularly check for new messages. In a GUI application the windows themselves will implement this mechanism. In a background task you will have to write your own code for this, though.
0
 

Author Comment

by:seinc
ID: 17099427
Thanks for all the advice. I am a newbie with Delphi, so I'm not sure how to implement many of these suggestions. It appears that Critical section is pretty straightforward to use, but how do I make a global variable that my spawned thread and main thread can access?
I can't really paste code because it would go on forever. I am tasked with adding this functionality to existing code. Basically what I have is this:

A windows service that runs the Indy HttpServer.
This windows service spawns a thread that listens on an Enterprise Service Bus for Joram messages.
When a message on a relevant topic is found, an xml Business Object Document ("BOD" based on Oagis) processor specific to that BOD type is instantiated.
This BOD processor inherits from a class that inherits from a class.
This BOD processor is supposed to communicate information  back to the windows service about if it is currently processing a BOD, and if it is, what is the BOD id, type, etc, etc.
The Indy HttpServer is supposed to respond with info sent by the BOD processor.

Maybe thread messages is not the way to go here. Maybe I create a webservice that the BOD processor updates, and the windows service reads?

0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

759 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now