【问题标题】:Access Violation on use OleVariant and TWebBrowser in a Thread在线程中使用 OleVariant 和 TWebBrowser 时访问冲突
【发布时间】:2014-11-20 16:12:19
【问题描述】:

我尝试在线程中通过 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

我需要帮助来解决这个问题。谢谢

【问题讨论】:

标签: multithreading delphi access-violation twebbrowser


【解决方案1】:

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

  1. 您正在使用 COM 而不在 TNavegar.Execute 中对其进行初始化。为了访问 COM 对象,您需要初始化 COM。
  2. 您正在一个线程中创建 COM 对象,然后从另一个线程中使用它。我认为这不适用于这个 COM 对象。

将 Web 浏览器 COM 对象的所有访问权限保持在同一个线程。一旦你这样做了,你可能还会发现你不再需要包含对Sleep 的极其可疑的调用。我的猜测是,这是为了让其他线程有机会开始并创建 COM 对象。每当您发现自己正在处理线程竞赛时,Sleep 都不是答案。

我的猜测是,您实际上并不需要两个线程,一个就足够了。我还想知道您是否真的需要网络浏览器控件。您不能使用简单的 HTTP 传输来执行此操作吗?这很可能让您停止调用 ProcessMessages,这是另一个大体上不应该被调用的函数。

【讨论】:

  • 嗨,执行命令中的 Delphi XE 不是必需的。我在另一个线程中使用,因为我需要在后台运行 WebBrowser。
  • 你好,朋友!我正在使用 WebBrowser,因为我需要操作 html,例如单击按钮、更改文本字段...
  • 用线程就好了。但你只需要一个。像这样使用两个是不好的。
  • @Senjaxus: TWebBrowser 是一个 visual 组件。它不应该在主 UI 线程之外使用,并且绝对不应该用于工作线程中的非可视工作。 TWebBrowser 在后台工作。 Navigate() 是异步的,它不会阻塞调用线程,当它完成时你会得到OnDocumentComplete 和/或OnDownloadComplete 事件。那么你到底想要完成什么?假设您想在没有用户交互的情况下将 Web 表单提交回服务器,您应该为此使用非可视 HTTP 客户端,例如 Indy 的 TIdHTTP
猜你喜欢
  • 2014-09-16
  • 1970-01-01
  • 2015-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-07
  • 2010-11-19
  • 2016-10-13
相关资源
最近更新 更多