2012-10-11 63 views
1

我有些遺傳代碼,打開IE瀏覽器,我有一些麻煩OLEOBJECT,這裏是我有:德爾福訪問來自2級不同的線程

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; 

我想有「全局」,即變量的單位和寫LoadIE程序是這樣的:

LoadIE應該FORMCREATE(主線程)被稱爲

它應該只是打造「全球」,即對象

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

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

所以問題是如何從2個不同的線程訪問相同的OLE對象,一個創建對象,另一個使用它。


當我寫的代碼,不帶螺紋的照顧我得到一個錯誤

異常類EOleSysError有消息

「叫這是整理爲不同的線程接口的應用」我應該怎麼做,照顧線程(我沒有線程經驗,一些閱讀和視頻鏈接是受歡迎的)。

在此先感謝

回答

2

如您所知,因爲它是your previous question的主題,所以您需要從同一個線程調用COM對象。主要的GUI線程是顯而易見的選擇。因此,請在主窗體的OnCreate事件處理程序中創建IWebBrowser2。然後在需要顯示瀏覽器時使用TThread.SynchronizeTThread.Queue。您傳遞給SynchronizeQueue的代碼將在主GUI線程上執行。

假設你正在使用德爾福的現代版,可支持匿名方法,你會寫這樣的:

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; 
+0

謝謝大家,我可能會嘗試從同一個線程中找到一種方法 – Milan

1

使用CriticalSection將所有調用包裝到OleObject。還可以使用Synchronize從「其他」線程調用主UI線程(這就是您獲得例外的原因)。

+0

爲什麼在確保所有對COM對象的訪問都來自同一個線程後,您需要使用關鍵部分? –

+0

如果對象的所有訪問都來自同一個線程,那麼您是對的,您不需要使用CriticalSection ... –

5

MTA model COM服務器只能在其關聯的公寓內使用。下面是與下面的通知錯誤的explanation

從一個單元傳遞接口指針(無論是直接 指針或代理指針)到另一個正確的方法是通過COM的 編組機制。源公寓可以撥打 CoMarshalInterThreadInterfaceInStream()來編組指向共享(全局)流的接口 指針。目的地公寓可通過撥打 CoGetInterfaceAndReleaseStream()解組此接口指針 。

+0

您是否推薦米蘭使用'CoMarshalInterThreadInterfaceInStream()'和'CoGetInterfaceAndReleaseStream()'? –

+0

@DavidHeffernan不,因爲沒有足夠的信息來推薦任何東西。我只是指出了文檔化的方式來訪問不同線程的COM對象,如果需要的話(可能是這種情況,正如問題所暗示的那樣)。 –

+0

嗯,我認爲足夠安全,建議只從一個線程調用COM對象。 –

1

非自由線程的COM對象只能由/上使用/在與其爲/ on/in/with創建的線程相同。在你的情況下,爲了加快速度,我會使用IWebBrowser2類型的普通全局值,或者類中的一個屬性重寫TThread。