| From: David Markie |
|
| Subject: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 4-Aug-2005 at 8:40:2 PST |
I have a D7 app that uses a TXMLDoucument successfully in the main thread, I
want to move some XML code into a TThread, passing the existing XMLDocument
into the thread fails when I call:-
XMLDocument1.XML.Clear;
XMLDocument1.LoadFromFile(XMLFilename); // fails here - filename is valid
XMLDocument1.Active:=true;
The error message is >>...raised exception class EOleSysError with message
'CoInitialise has not been called'<<
Creating a new TXMLDocument within the thread also fails at the same point.
Is there an inherent problem in using TXMLDocument inside a Thread
Thanks
David
|
| From: Remy Lebeau \(TeamB\) |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 4-Aug-2005 at 18:20:5 PST |
"David Markie" wrote in message
news:42f2ae37@newsgroups.borland.com...
> is this the correct use of CoInitialize and CoUnInitialize
Yes, but that is not what is wrong with your code.
> as the XML code still fails but this time with an AV
You are not using TXMLDocument properly. When instantiated dynamically,
TXMLDocument acts as an interface, not a component. As such, you need to
treat it as an interface. In which case, you may as well use real
interfaces instead, via the NewXMLDocument() and related functions, ie:
procedure TXMLFileThread.Execute;
var
XMLDoc: IXMLDocument;
begin
CoInitialize(nil);
try
XMLDoc := NewXMLDocument;
// perform XML Stuff...
except
// ReportErrors;
end;
CoUnInitialize();
end;
Gambit
|
| From: David Markie |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 5-Aug-2005 at 1:9:56 PST |
My thread execute method is shown below, is this the correct use of
CoInitialize and CoUnInitialize, as the XML code still fails but this time
with an AV
procedure TXMLFileThread.Execute;
begin
CoInitialize(nil);
try
FXMLDocument:=TXMLDocument.create(nil);
try
perform XML Stuff... // still fails here but this time with an AV
finally
FreeAndNil(FXMLDocument);
end;
except
// ReportErrors;
end;
CoUnInitialize();
end;
The code that works is contained in a unit with the TXMLDocument declared
as:-
unit XML_Unit;
interface
uses
classes,sysutils,forms,XMLIntf,XMLDoc;
implementation
var
XMLDocument1: TXMLDocument;
XML methods....
initialization
XMLDocument1:=TXMLDocument.create(application);
finalization
end.
The code in the unit failed when XMLDocument1:=TXMLDocument.create(nil); was
used so I had to find a willing owner hence 'uses forms' and
'create(application)'
It did feel like a fudge when I wrote it but could not see a clear solution
David
|
| From: Ronaldo Souza |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 4-Aug-2005 at 13:30:34 PST |
>
> If an exception occurs, CoUnitialize() is being bypassed. You should be
> placing the CoInitialize/CoUninitialize() outside the try..except block:
>
Good catch Gambit! Thanks.
|
| From: Remy Lebeau \(TeamB\) |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 4-Aug-2005 at 1:26:26 PST |
"Ronaldo Souza" wrote in message
news:42F1CC36.3010202@nospam.org...
> Should look something like this:
If an exception occurs, CoUnitialize() is being bypassed. You should be
placing the CoInitialize/CoUninitialize() outside the try..except block:
procedure TMyXMLThread.Execute
begin
CoInirialize(nil);
try
// ...
except
//No exceptions should escape...
end;
CoUninitialize;
end;
Alternatively, override the thread's DoTerminate() method as well. Then you
don't need the try..except at all, as it won't matter anymore if an
exception is thrown:
procedure TMyXMLThread.Execute
begin
CoInirialize(nil);
// ...
end;
procedure TMyXMLThread.DoTerminate;
begin
CoUninitialize;
end;
Gambit
|
| From: Remy Lebeau \(TeamB\) |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 4-Aug-2005 at 1:23:47 PST |
"David Markie" wrote in message
news:42f1c642$1@newsgroups.borland.com...
> I want to move some XML code into a TThread, passing the
> existing XMLDocument into the thread
You should not do that. TXMLDocument is tied to the thread that creates it.
This is especially important if you use MSXML as the core engine, as MSXML
is a COM object and thus cannot be passed around between multiple threads.
You are best off simply creating a new TXMLDocument instance in the thread's
Execute() method to ensure proper usage for that thread.
> The error message is >>...raised exception class EOleSysError
> with message 'CoInitialise has not been called'<<
>
> Creating a new TXMLDocument within the thread also fails
> at the same point.
The error is self-explanatory. Your thread did not call the CoInitialize()
function before accessing the TXMLDocument. Which likely meansthat you are
indeed using the MSXML engine. All threads much call either CoInitialize()
or CoInitializeEx() before accessing any COM objects and/or functions.
Gambit
|
| From: Ronaldo Souza |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 4-Aug-2005 at 5:5:10 PST |
David,
Add a call to CoInitialise and CoUnitiliase in the Execute procedure of
your thread. Should look something like this:
uses
ActiveX;
procedure TMyXMLThread.Execute
begin
try
CoInirialize(nil);
. . .
while not terminated do
begin
. . .
//Do XML stuff here
. . .
end;
. . .
CoUninitialize;
except
//No exceptions should escape...
end;
end;
Good luck,
Ronaldo
|
| From: David Markie |
|
| Subject: Re: Using TXMLDocument in a Thread |
| NewsGroup: borland.public.delphi.vcl.components.using.win32 |
| Date Posted: 7-Aug-2005 at 16:22:34 PST |
All working now - thanks for the assistance
David
|