Multithreading – how does a thread notify an object without a window handle?
I'm new to multithreading, but I'm not a complete novice I need to execute the call to the web service in the worker thread
In the main thread, I have a form (tform), which has a private data member (private string), which can only be written by the working thread (I pass the pointer to the thread before it recovers) When the worker thread completes its WebService call and writes the result response XML to the private member on the form, the worker thread uses PostMessage to send the message to the handle of the form (I passed it to the thread before recovery)
interface const WM_WEBSERVCALL_COMPLETE = WM_USER + 1; type TWebServiceResponseXML = string; PWebServiceResponseXML = ^TWebServiceResponseXML; TMyForm = class(TForm) ... private ... fWorkerThreadID: Cardinal; fWebServiceResponseXML: TWebServiceResponseXML; public ... procedure StartWorkerThread; procedure OnWebServiceCallComplete(var Message: TMessage); Message WM_WEBSERVCALL_COMPLETE; end; TMyThread = class(TThread) private protected procedure Execute; override; public SenderHandle: HWnd; RequestXML: string; ResponseXML: string; IMyService: IService; PResponseXML: PWebServiceResponseXML; end; implementation procedure TMyForm.StartWorkerThread; var MyWorkerThread: TMyThread; begin MyWorkerThread := TMyThread.Create(True); MyWorkerThread.FreeOnTerminate := True; MyWorkerThread.SenderHandle := self.Handle; MyWorkerThread.RequestXML := ComposeRequestXML; MyWorkerThread.PResponseXML := ^fWebServiceResponseXML; MyWorkerThread.Resume; end; procedure TMyForm.OnWebServiceCallComplete(var Message: TMessage); begin // Do what you want with the response xml string in fWebServiceResponseXML end; procedure TMyThread.Execute; begin inherited; CoInitialize(nil); try IMyService := IService.GetMyService(URI); ResponseXML := IMyService.Search(RequestXML); PResponseXML := ResponseXML; PostMessage(SenderHandle,WM_WEBSERVCALL_COMPLETE,0); finally CoUninitialize; end; end;
It works well, but now I want to do the same thing from the data module (no handle)... So I really appreciate some useful code to supplement my working model
edit
What I really want is the code that allows me to replace the line (if possible)
MyWorkerThread.SenderHandle := self.Handle;
with
MyWorkerThread.SenderHandle := GetHandleForThisSOAPDataModule;
Solution
I have used this technology before and achieved some success: sending messages to non windowed applications
Basically, the second thread is used as the message pump on the handle obtained through allocatehwnd This is no doubt annoying. You'd better use the library to handle all the details I prefer omnithreadlibrary, but there are others – see how do I choose between the various ways to do threading in Delphi? And Delphi – threading frameworks