Appropriate way to solve such problem is to create a descendant of the TOmniWorker object and move THTTPRIO/THTTPReqResp there. You should also create and destroy them inside the thread, and you should declare all event handlers as methods inside this descendant of the TOmniWorker object. Like this:
type
TMoviesTask = class(TOmniWorker)
strict private
FHTTPReqResp: THTTPReqResp;
FHTTPRIO: THTTPRIO;
protected
procedure CreateRIO;
procedure DestroyRIO;
procedure HTTPReqRespBeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);
procedure HTTPRIOAfterExecute(const MethodName: string; SOAPResponse: TStream);
procedure HTTPRIOBeforeExecute(const MethodName: string; SOAPRequest: TStream);
procedure HTTPReqRespPostingData(Sent, Total: Integer);
procedure HTTPReqRespReceivingData(Read, Total: Integer);
public
procedure GetTop10;
end;
procedure TMoviesTask.CreateRIO;
begin
FHTTPReqResp := THTTPReqResp.Create(nil);
with FHTTPReqResp do begin
Name := 'HTTPReqRespTask' + IntToStr(Task.UniqueID);
UseUTF8InHeader := True;
InvokeOptions := [soIgnoreInvalidCerts, soAutoCheckAccessPointViaUDDI];
WebNodeOptions := [];
OnBeforePost := HTTPReqRespBeforePost;
OnPostingData := HTTPReqRespPostingData;
OnReceivingData := HTTPReqRespReceivingData;
end;
FHTTPRIO := THTTPRIO.Create(nil);
with FHTTPRIO do begin
Name := 'HTTPRIOTask' + IntToStr(Task.UniqueID);
OnAfterExecute := HTTPRIOAfterExecute;
OnBeforeExecute := HTTPRIOBeforeExecute;
HTTPWebNode := FHTTPReqResp;
end;
end;
procedure TMoviesTask.HTTPReqRespBeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);
begin
Task.Comm.Send(SOAP_MSG, Format('CurrThread %d : MainThread %d ', [GetCurrentThreadId(), MainThreadID]) + 'HTTPReqResp1BeforePost');
end;
procedure TMoviesTask.GetTop10;
var
res: TopMovies.ArrayOfString;
I: Integer;
resList: TStringList;
begin
if CoInitializeEx(nil, COINIT_MULTITHREADED or COINIT_SPEED_OVER_MEMORY) = S_OK then try
CreateRIO;
try
try
res := GetTopMoviesSoap(False, '', FHTTPRIO).GetTop10;
resList := TStringList.Create;
if Length(res) > 0 then
for I := 0 to Length(res) - 1 do
resList.Add(res[I]);
task.Comm.Send(SOAP_DONE, resList);
except
on E: Exception do
task.Comm.Send(SOAP_DONE, E);
end;
finally DestroyRIO; end;
finally CoUninitialize; end;
end;
procedure TMainForm.btnGetTop10Omni1Click(Sender: TObject);
begin
lbLog.Clear;
lbLog.Items.Add(Format('CurrThread %d : MainThread %d ', [GetCurrentThreadId(), MainThreadID]) + 'btnGetTop10Omni1Click start');
lbSoapResponse.Clear;
FGetSoapTask := CreateTask(TMoviesTask.Create(), 'MoviesTask')
.OnMessage(
{$REGION 'Message handler'}
procedure(const task: IOmniTaskControl; const msg: TOmniMessage)
begin
case msg.MsgID of
SOAP_MSG:
lbLog.Items.Add(msg.MsgData);
SOAP_DONE:
begin
lbSoapResponse.Items := TStrings(msg.MsgData.AsObject);
end;
SOAP_ERROR:
begin
lbLog.Items.Add(Format('CurrThread %d : MainThread %d ', [GetCurrentThreadId(), MainThreadID])
+ 'Error: ' + msg.MsgData.AsException.Message);
end;
end;
end)
{$ENDREGION}
.Run.Invoke(@TMoviesTask.GetTop10);
lbLog.Items.Add(Format('CurrThread %d : MainThread %d ', [GetCurrentThreadId(), MainThreadID]) + 'btnGetTop10Omni1Click end');
end;
Full object is attached.
I can not, however, destroy THTTPRIO/THTTPReqRequest components in the thread. If I try this, I'm getting back Invalid Pointer exception from the VCL and I can't tell what's going wrong. (This happens in XE2, didn't try other Delphis.)
I think I'll ask on StackOverflow for help with this detail ...