Access Violation on use OleVariant and TWebBrowser in a Thread

808 views Asked by At

i try control a TWebBrowser by OleVariant in a Thread, but i get Access Violation Error. The error only occurs when I use the following code in Delphi XE6:

var
  Elements: OleVariant;
begin
    Elements := Criar.Web.OleObject.document.all;
end;

Being that "Criar" is a Thread.

See the full code:

type
  TCriarWeb = class(TThread)
    protected procedure Execute; override;
    public
      Web: TWebBrowser;
  end;

type
  TNavegar = class(TThread)
    protected procedure Execute; override;
    public
  end;

procedure TNavegar.Execute;
var
  Criar: TCriarWeb;
  Elements: OleVariant;
  i: Integer;
begin
  inherited;
  Criar := TCriarWeb.Create;
  Sleep(500);

  for i := 0 to 100 do begin
    Criar.Web.Navigate('http://www.google.com');
    while Criar.Web.ReadyState <> READYSTATE_COMPLETE do
      Sleep(100);

    Elements := Criar.Web.OleObject.document.all;


  end;
end;

{ TCriarWeb }

procedure TCriarWeb.Execute;
begin
  inherited;

  CoInitialize(nil);
  Web := TWebBrowser.Create(nil);
  Web.HandleNeeded;
  Web.Silent := true;

  while true do
    Application.ProcessMessages;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Navegar: TNavegar;
begin
  Navegar := TNavegar.Create;

end;

Follow the link to download the sources: https://www.dropbox.com/s/di3oou8a7ztg22m/Tentativa%20Webbrowser.rar?dl=0

I need a help for resolve this problem. Thanks

1

There are 1 answers

4
David Heffernan On

You have two major problems that I can see:

  1. You are using COM without initializing it in TNavegar.Execute. In order to access a COM object you do need to initialize COM.
  2. You are creating the COM object in one thread but then using it from another thread. I don't think that is going to work out for this COM object.

Keep all the access of the web browser COM object to the same thread. And once you do that you'll probably also find that you no longer need to include that extremely dubious call to Sleep. My guess is that is there to give the other thread a chance to get going and create the COM object. Any time you find yourself dealing with a threading race, Sleep is not the answer.

My guess is that you don't actually need two threads here and that one will suffice. I also wonder whether or not you really need a web browser control. Can't you do this using a simple HTTP transfer? This might very well allow you to stop calling ProcessMessages, another function that, by and large, should never be called.