Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Client in Thread.

70 views
Skip to first unread message

Stig Johansen

unread,
Nov 7, 2001, 3:27:28 AM11/7/01
to
Hi.

I have a multithreaded app server, that in a thread makes a soap request to
a soap server.
The threads are pooled.

If i use the following construct:
In Thread.create:
HTTPRIO := THTTPRIO.Create
HTTPRIO.URL := 'My url';

In Thread.Destroy:
HTTPRIO.Free;

It works for one or two requests. After that it chrashes with Runtime error
0.

If I on the other hand in theexecute method uses:
HTTPRIO := THTTPRIO.Create
HTTPRIO.URL := 'My url';
Do request
HTTPRIO.Free;

It works.

It seems like I have to do some 'reinitializing' with the HTTPRIO after each
call, but what?

NB: It is on Kylix.

Regards
Stig Johansen.

Damiano Curia

unread,
Nov 7, 2001, 3:45:32 AM11/7/01
to
I can only say that in this way the HTTPRIO isn't created in the secondary
thread, but in the main thread.
I created HTTPRIOs in the secondary thread and I see I can't call their
methods by the main thread, while all was ok if I called the methods inside
the thread.
I don't know, maybe even the viceversa isn't applicable.
Bye, Damiano Curia

PS: remember CoInitialize/CoUninitialize inside the Execute method.


Stig Johansen

unread,
Nov 7, 2001, 4:43:53 AM11/7/01
to
Hi.
"Damiano Curia" <cur...@euroforex.com> wrote in message
news:3be8f499$1_1@dnews...

> I can only say that in this way the HTTPRIO isn't created in the secondary
> thread, but in the main thread.
> I created HTTPRIOs in the secondary thread and I see I can't call their
> methods by the main thread, while all was ok if I called the methods
inside
> the thread.

I am declaring, creating and calling all in the same thread.
The HTTPRIO is declared in the private section of the thread.

It seems like if it is 'resused', there are something missing between the
calls.

Maybe this is a pure Kylix issue, so maybe i have to wait until my K2
arrives?.
(no source->debugging i the trial version)

regards
Stig Johansen.


Damiano Curia

unread,
Nov 7, 2001, 5:19:34 AM11/7/01
to
> I am declaring, creating and calling all in the same thread.
In thread create you aren't in the thread! You are in the calling thread.
Bye, Damiano Curia


Shiv Kumar

unread,
Nov 7, 2001, 12:11:32 PM11/7/01
to
Stig,

You're problem pertains to the fact that HTTPRIO is life time managed if
it's owner is nil. Take a look at the tutorial on my web site called -
building your first web service. There is a section called THHTPRIO
Explained. You'll most likely find your answer there.

--
Shiv Kumar
The Delphi Apostle
http://www.matlus.com
http://www.delphisoap.com


Stig Johansen

unread,
Nov 7, 2001, 4:12:35 PM11/7/01
to
Damiano Curia wrote:

I have tried to create the HTTPRIO in the .execute method, but it does'nt
make any difference.

--
Med venlig hilsen / Best regards
Stig Johansen
li...@w3data.dk

Stig Johansen

unread,
Nov 7, 2001, 4:40:02 PM11/7/01
to
Shiv Kumar wrote:

> Stig,
>
> You're problem pertains to the fact that HTTPRIO is life time managed if
> it's owner is nil. Take a look at the tutorial on my web site called -
> building your first web service. There is a section called THHTPRIO
> Explained. You'll most likely find your answer there.

Well, i create the HTTPRIO in
a) The .create method of my thread
or
b) As the very first of my .execute of the thread

Then i 'reuse' the HTTPRIO during the threads lifetime, where it will never
be = nil, and therefore should be intact.

Then i free it in the .destroy method of the thread.

I cannot see why it should not work.

As John Hutchkins pointed out in a previous thread:
FHTTP.HTTPWebNode.Connect(false);//somebody said this stops mem leaks

Maybe the problem lies here, but in my Kylix 2 (I know that i am a little
bit early out here), the method
HTTPRIO.HTTPWebNode.Connect
does not exist.

Stig Johansen

unread,
Nov 7, 2001, 6:02:32 PM11/7/01
to
Shiv Kumar wrote:

> Stig,
>
> I was talking about the "Owner" of the THTTPRIO component...
>
> When you create an instance (preferably in the Execute method by the way),
> do you set the owner to nil. Most probably, since you don't really have an
> "owner" you can use.

Yes, i know.

> If so, then the component will be freed automatically
> for you since it will be treated like an interface (life time managed)
> rather than a component.

Yes, i know.

>
> So don't free it in the thread. Now I've not tried this in a thread, but
> it's probably what you need to do to get this to work.

Shiv, i am basically not talking about to get it to work. I am talking
about the following (pseudo) structures:

-- works only once --
HTTPRIO := THTTPRIO.Create(Nil);
REPEAT
Use HTTPRIO
UNTIL Done
HTTPRIO.Free;

vs.

-- works alle the time, but performance? --
REPEAT
HTTPRIO := THTTPRIO.Create(Nil);
Use HTTPRIO
HTTPRIO.Free;
UNTIL Done;

Please excuse me if i am not so clear, but English is not my native
language.

Shiv Kumar

unread,
Nov 7, 2001, 6:55:01 PM11/7/01
to
Ok,

I didn't get that in your first post. I might have missed the explanation.
But I understand now. Thanks for the clarification.

I'd still not "free" the instance after you're done using it (considering
that you'll be leaving the execute method and so it will go out of scope).

What are you doing when you "use" the HTTPRIO instance?

When you say "works only once". Is it once in the loop? Or it doesn't work
the next time around when you create it?

Sorry, I'm just trying to understand this. I may not have a solution for you
<g>

Jean-Marie Babet

unread,
Nov 7, 2001, 7:02:09 PM11/7/01
to
Stig,

> -- works only once --
> HTTPRIO := THTTPRIO.Create(Nil);
> REPEAT
> Use HTTPRIO
> UNTIL Done
> HTTPRIO.Free;

Two questions:

1. Are you using the HTTPRIO for the same interface in the loop that only
works the first time?

2. If yes to above, are you making sure that you hang on to that interface
to ensure that the HTTPRIO's ref. count does not reach '0' and the component
destroys itself after the first pass through?

Regards,


Bruneau.

PS: As Shiv pointed out, avoid calling 'HTTPRIO.Free' if the component is
created with a 'Nil' owner. Unless you never use the component (i.e. you
never query for an interface from it).

"Shiv Kumar" <sh...@erols.com> wrote in message news:3be9c9ec_1@dnews...

Jean-Marie Babet

unread,
Nov 7, 2001, 6:57:36 PM11/7/01
to
> Maybe the problem lies here, but in my Kylix 2 (I know that i am a little
> bit early out here), the method
> HTTPRIO.HTTPWebNode.Connect
> does not exist.

Stig,

Sorry for jumping in here. I just wanted to mention that the HTTPWebNode is
implemented with WinInet in Delphi and with Indy in Kylix. We tried to keep
the basic premise of the component identical in both implementations.
However, some methods did not make sense in one or the other. Connect() is
one of those that did not make sense with Indy.

Since Kylix went out, I've merged the two implementations so that you can
switch back and forth (under Windows that is):

Regards,


Bruneau.

=============== [ WinInet/Indy implementations merged ] ==================

THTTPReqResp = class(TComponent, IInterface, IWebNode, IHTTPReqResp)
private
FUserSetURL: Boolean;
FRefCount: Integer;
FOwnerIsComponent: Boolean;
FConnected: Boolean;
FURL: string;
FAgent: string;
FUserName: string;
FPassword: string;
FURLHost: string;
FURLSite: string;
FURLPort: Integer;
FURLScheme: Integer;
FProxy: string;
FProxyByPass: string;
{$IFNDEF USE_INDY}
FInetRoot: HINTERNET;
FInetConnect: HINTERNET;
{$ENDIF}
FWSDLView: TWSDLView;
FSoapAction: string;
FUseUTF8InHeader: Boolean;
FInvokeOptions: TSOAPInvokeOptions;
procedure SetURL(const Value: string);
function GetSOAPAction: string;
procedure SetSOAPAction(const SOAPAction: string);
procedure SetWSDLView(const WSDLVIew: TWSDLView);
function GetSOAPActionHeader: string;
procedure InitURL(const Value: string);
protected
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
constructor Create(Owner: TComponent); override;
class function NewInstance: TObject; override;
procedure AfterConstruction; override;
destructor Destroy; override;
function GetHTTPReqResp: THTTPReqResp;
{$IFNDEF USE_INDY}
procedure Check(Error: Boolean);
procedure Connect(Value: Boolean);
function Send(const S: WideString): Integer;
function SendGet: Integer;
procedure Receive(Context: Integer; Resp: TStream);
{$ENDIF}
{$IFDEF USE_INDY}
procedure SetupIndy(IndyHttp: TIDHttp);
{$ENDIF}
procedure Get(Resp: TStream); virtual;
procedure Execute(const DataMsg: WideString; Resp: TStream); virtual;
property URL: string read FURL write SetURL;
property SoapAction: string read GetSOAPAction write SetSOAPAction;
published
property WSDLView: TWSDLView read FWSDLView write SetWSDLView;
property Agent: string read FAgent write FAgent;
property UserName: string read FUserName write FUserName;
property Password: string read FPassword write FPassword;
property Proxy: string read FProxy write FProxy;
property ProxyByPass: string read FProxyByPass write FProxyByPass;
property UseUTF8InHeader: Boolean read FUseUTF8InHeader write
FUseUTF8InHeader;
property InvokeOptions: TSOAPInvokeOptions read FInvokeOptions write
FInvokeOptions;
end;


=============== [ WinInet/Indy implementations merged ] ==================


"Stig Johansen" <li...@w3data.dk> wrote in message news:3be9a962_2@dnews...

Shiv Kumar

unread,
Nov 7, 2001, 5:15:04 PM11/7/01
to
Stig,

I was talking about the "Owner" of the THTTPRIO component...

When you create an instance (preferably in the Execute method by the way),
do you set the owner to nil. Most probably, since you don't really have an

"owner" you can use. If so, then the component will be freed automatically


for you since it will be treated like an interface (life time managed)
rather than a component.

So don't free it in the thread. Now I've not tried this in a thread, but


it's probably what you need to do to get this to work.

Stig Johansen

unread,
Nov 8, 2001, 12:52:22 AM11/8/01
to
Jean-Marie Babet wrote:

> Stig,
>
>> -- works only once --
>> HTTPRIO := THTTPRIO.Create(Nil);
>> REPEAT

I am calling i.e ( i have inserted linebreaks):
fResponse.Text := (HTTPRIO as IIoagsoap).Add_Po(
fThreadData.ValuePairs.VarByName['PARTY_SITE_ID'],
fThreadData.ValuePairs.VarByName['USERNAME'],
fThreadData.ValuePairs.VarByName['PASSWORD'],fThreadData.ValuePairs.VarByName['PAYLOAD']);

>> UNTIL Done
>> HTTPRIO.Free;
>
> Two questions:
>
> 1. Are you using the HTTPRIO for the same interface in the loop that only
> works the first time?

It excactly the same call, but with diffrent parameters for each call. The
idea is, that the HTTPRIO exists during the lifetine of the thread.

>
> 2. If yes to above, are you making sure that you hang on to that interface
> to ensure that the HTTPRIO's ref. count does not reach '0' and the
> component destroys itself after the first pass through?

The code involved is really simple, for each request, i have an
ClientExecute:

procedure tmicroclientHTTPDispatcherthread.ClientExecute;
begin
Inherited ;
// writeln('Client thread started ',RemoteAddr,' - ',RemoteHost);

WRITELN('Calling soap handler');

TRY
// To move to initialize section
HTTPRIO := THTTPRIO.Create(NIL) ;
HTTPRIO.URL := 'HTTP://myurl:8080/liboagsoap.so/soap/IIoagsoap';

fResponse.Text := (HTTPRIO as
IIoagsoap).Add_Po(fThreadData.ValuePairs.VarByName['PARTY_SITE_ID'],fThreadData.ValuePairs.VarByName['USERNAME'],fThreadData.ValuePairs.VarByName['PASSWORD'],fThreadData.ValuePairs.VarByName['PAYLOAD']);
// To move to destroy section
HTTPRIO.Free ;

EXCEPT ON E:Exception DO
fResponse.Text := '<HTML><BODY>Error : '+E.Message+'</BODY></HTML>';
END;

end;


I am not really sure what is happening, right now the second call just
hangs.

Regards
Stig Johansen.

>
> Regards,
>
>
> Bruneau.
>
> PS: As Shiv pointed out, avoid calling 'HTTPRIO.Free' if the component is
> created with a 'Nil' owner. Unless you never use the component (i.e. you
> never query for an interface from it).
>
>
>
> "Shiv Kumar" <sh...@erols.com> wrote in message news:3be9c9ec_1@dnews...
>> Ok,
>>
>> I didn't get that in your first post. I might have missed the
>> explanation. But I understand now. Thanks for the clarification.
>>
>> I'd still not "free" the instance after you're done using it (considering
>> that you'll be leaving the execute method and so it will go out of
>> scope).
>>
>> What are you doing when you "use" the HTTPRIO instance?

See above.

>>
>> When you say "works only once". Is it once in the loop? Or it doesn't
>> work the next time around when you create it?

If I create it once in the thread, and calls it several times, the first
call is ok.
When the second call is made, it either hangs or chashes.

If i do as above, it works every time.

>>
>> Sorry, I'm just trying to understand this. I may not have a solution for
> you
>> <g>
>> --
>> Shiv Kumar
>> The Delphi Apostle
>> http://www.matlus.com
>> http://www.delphisoap.com
>>
>>

--

Stig Johansen

unread,
Nov 8, 2001, 1:10:55 AM11/8/01
to
Jean-Marie Babet wrote:

>> Maybe the problem lies here, but in my Kylix 2 (I know that i am a little
>> bit early out here), the method
>> HTTPRIO.HTTPWebNode.Connect
>> does not exist.
>
> Stig,
>
> Sorry for jumping in here. I just wanted to mention that the HTTPWebNode
> is implemented with WinInet in Delphi and with Indy in Kylix. We tried to

Does that mean, that Borland officially supports Indy instead of its own
Socket components?

> keep the basic premise of the component identical in both implementations.
> However, some methods did not make sense in one or the other. Connect() is
> one of those that did not make sense with Indy.

Thanks for the info. I have not used Indy for my server programming.
Maybe it's only useable in desktop applications.

>
> Since Kylix went out, I've merged the two implementations so that you can
> switch back and forth (under Windows that is):

Well i have to be patient until my K2 arrives, so i can debug/patch it.

Jean-Marie Babet

unread,
Nov 8, 2001, 12:12:46 PM11/8/01
to
Stig,

One of the problem I see is the following line:

fResponse.Text := (HTTPRIO as IIoagsoap).Add(......)

This will retrieve an 'IIoagsoap' interface from the RIO. The code is not
hanging on to that interface. As soon as the interface goes away (i.e. is
released) - that's taken care of for you by 'managed code' generated by the
compiler - the HTTPRIO is destroyed. You can restructure the code as
follows:

var
Service: IIoagsoap;

HTTPRIO := THTTPRIO.Create(nil)
Service := (HTTPRIO as IIoagsoap);
REPEAT
fResponse.Text := Service.Add_Po(.....);
UNTIL Done


And again, do *NOT* call HTTPRIO.Free on an HTTPRIO that was created with
'nil' as owner.

The above should achieve what you're after - which is avoid overhead of
constantly creating a new HTTPRIO. Let me know if it does not.

Regards,


Bruneau.


Jean-Marie Babet

unread,
Nov 8, 2001, 12:15:11 PM11/8/01
to
> Does that mean, that Borland officially supports Indy instead of its own
> Socket components?

Yes both Delphi and Indy ship with Indy. Delphi SOAP did not use Indy
(primarily because of the lack of SSL support, which has been addressed in a
later version of Indy v 9.0). Kylix SOAP uses Indy.

Regards,


Bruneau.

Stig Johansen

unread,
Nov 8, 2001, 1:43:55 PM11/8/01
to
Jean-Marie Babet wrote:

> Stig,
>
> One of the problem I see is the following line:
>
> fResponse.Text := (HTTPRIO as IIoagsoap).Add(......)
>

> var
> Service: IIoagsoap;
>
> HTTPRIO := THTTPRIO.Create(nil)
> Service := (HTTPRIO as IIoagsoap);
> REPEAT
> fResponse.Text := Service.Add_Po(.....);
> UNTIL Done

Got it, works beautifully.

>
>
> And again, do *NOT* call HTTPRIO.Free on an HTTPRIO that was created with
> 'nil' as owner.

Yes yes, sorry, i am listening.

>
> The above should achieve what you're after - which is avoid overhead of
> constantly creating a new HTTPRIO. Let me know if it does not.
>

It does work, thanks very much for the help.

0 new messages