在线程中使用OleVariant和TWebBrowser时访问冲突

时间:2014-11-20 16:12:19

标签: multithreading delphi access-violation twebbrowser

我尝试在线程中通过OleVariant控制TWebBrowser,但是我得到了访问冲突错误。只有在Delphi XE6中使用以下代码时才会出现错误:

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

因为“Criar”是一个线程。

请参阅完整代码:

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;

点击链接下载资源:https://www.dropbox.com/s/di3oou8a7ztg22m/Tentativa%20Webbrowser.rar?dl=0

我需要帮助才能解决此问题。感谢

1 个答案:

答案 0 :(得分:2)

我可以看到两个主要问题:

  1. 您正在使用COM而未在TNavegar.Execute中初始化它。要访问COM对象,您需要初始化COM。
  2. 您正在一个线程中创建COM对象,然后从另一个线程使用它。我认为这不会影响这个COM对象。
  3. 保持Web浏览器COM对象的所有访问权限到同一个线程。一旦你这样做,你可能也会发现你不再需要将这个非常可疑的电话包含在Sleep中。我的猜测就是让其他线程有机会开始创建COM对象。每当你发现自己正在处理穿线比赛时,Sleep就不是答案了。

    我的猜测是你实际上并不需要两个线程,而且一个就足够了。我也想知道你是否真的需要一个网页浏览器控件。你不能使用简单的HTTP传输吗?这可能会让你停止调用ProcessMessages,这个函数根本就不应该被调用。