Delphi从2个不同的线程访问OleObject

时间:2012-10-11 13:31:32

标签: multithreading delphi ole

我有一些用于打开IE的继承代码,我有一些麻烦,这就是我所拥有的:

IEUnit.pas(无表格)具有LoadIE和OpenIE的例程

从单独的线程调用OpenIE,它看起来像这样

procedure OpenIE(URL: OleVariant; FieldValues: string = '');
var ie : IWebBrowser2; // <-- This should become "global" variable for the IEUnit
begin
  ie := CreateOleObject('InternetExplorer.Application') as IWebBrowser2;
  ie.Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
  ShowWindow(ie.HWND, SW_SHOWMAXIMIZED);
  ie.Visible := true;
  ...
end;

我想在单元中使用“global”即变量,并像这样编写LoadIE例程:

应从FormCreate(主线程)

调用LoadIE

它应该只创建“全局”即对象

  ie := CreateOleObject('InternetExplorer.Application') as IWebBrowser2;

所以OpenIE功能不需要创建它,只是为了使用它(目的是加快速度)

所以问题是如何从2个不同的线程访问同一个OLE对象,一个创建对象,另一个使用它。


当我编写不处理线程的代码时,我收到错误

异常类EOleSysError,消息'应用程序称为为不同线程编组的接口'

我该怎么做,照顾线程(我没有线程经验,欢迎阅读和视频链接。)

提前致谢

4 个答案:

答案 0 :(得分:5)

MTA model COM服务器只能在其关联的公寓中使用。这是错误的explanation,其中包含以下建议:

  

传输接口指针的正确方法(直接指向   指针或代理指针)从一个公寓到另一个公寓是通过COM公司   编组机制。来源公寓可以打电话   CoMarshalInterThreadInterfaceInStream()编组接口   指向共享(全局)流的指针。目的地公寓可以   通过调用解组此接口指针   CoGetInterfaceAndReleaseStream()

答案 1 :(得分:2)

如您所知,因为它是your previous question的主题,所以您需要从同一个线程对COM对象进行所有调用。显而易见的选择是主要的GUI线程。因此,在主窗体的IWebBrowser2事件处理程序中创建OnCreate。然后在需要显示浏览器时使用TThread.SynchronizeTThread.Queue。传递给SynchronizeQueue的代码将在主GUI线程上执行。

假设您正在使用支持匿名方法的现代版Delphi,您可以这样写:

procedure TMyThread.ShowBrowser(const URL: string);
var
  Proc: TThreadProcedure;
begin
  Proc := procedure
    begin
      MainForm.Browser.Navigate2(URL, ...);
      ShowWindow(MainForm.Browser.HWND, SW_SHOWMAXIMIZED);
      MainForm.Browser.Visible := true;
    end;
  Queue(Proc);
end;

答案 2 :(得分:1)

使用CriticalSection来包装对OleObject的所有调用。还可以使用Synchronize从“其他”线程调用主UI线程(这就是你获得异常的原因)。

答案 3 :(得分:1)

非自由线程COM对象只能由/ on /在与/ on / in / with创建的线程相同的线程中使用。在你的情况下,为了加快速度,我会使用类型为IWebBrowser2的普通全局treadvar值,或者类中覆盖TThread的属性。