seinc
asked on
How to send message from thread to main thread?
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.
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.
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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/Set Event/Rese tEvent 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.
Or you use a Windows event with the CreateEvent/PulseEvent/Set
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.
ASKER
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?
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?
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.UpdateServic
begin
// Running in context of main thread
svcSample.UpdateServiceSta
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
begin
// Handle the control code
svcSample.Controller(CtrlC
end;
function TsvcSample.GetServiceContr
begin
// Return the service controller
Result:=ServiceController;
end;
procedure TsvcSample.ServiceStart(Se
begin
// Create the worker thread
FWorker:=TWorkerThread.Cre
end;
procedure TsvcSample.ServicePause(Se
begin
// Pause the worker thread
FWorker.Suspend;
end;
procedure TsvcSample.ServiceContinue
begin
// Resource protection
try
// Resume the worker thread
FWorker.Resume;
finally
// Continue the service
Continued:=True;
end;
end;
procedure TsvcSample.ServiceStop(Sen
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.UpdateServiceSt
begin
// Update from worker thread
MessageBox(0, PChar(Value), 'Worker Update', MB_OK or MB_SERVICE_NOTIFICATION);
end;
end.