[英]VB6 GUI not working in multithreaded COM environment
我有一個調用進程內 STA ATL/COM 服務器的 VB6 COM 客戶端。 服務器方法之一,X,可能需要一段時間才能完成,所以我需要能夠取消它。 我嘗試的是在新線程中運行方法代碼並包含另一個方法 Y,它執行定時 WaitForSinleObject。 所以客戶端首先調用 X 然后進入循環調用 VB6 DoEvents 然后 Y 直到 Y 指示 X 已經完成。 這工作正常,但是,美中不足的是 X 線程還通過 IConnectionPoint 接口將事件觸發回客戶端。 事件通過正常,但任何 GUI 調用都不起作用,因為據我所知,GUI 只能在一個線程上工作,即主線程。
使用我現有的代碼有沒有明顯的方法來解決這個問題? 或者,請您建議我可以完成的其他方法。
您應該始終編組您的連接點調用。 當你不這樣做時,你可以調用 VB 代碼,但它以隨機方式失敗(非編組對象),或者只是不起作用(GUI)。
要使用封送處理,您必須實現多個接口(見下文)。
另一種可能性是將對 VB 的異步調用轉換為同步“獲取”調用。
所以你的代碼來自(在C偽代碼中......):
while( !wait( X ) )
{
doevents();
}
到 :
while( !wait( X ) )
{
doevents();
fetch_async_data();
}
1) 通過將編組器添加到 COM_AGGRGATE 表,將編組器添加到您的類中:
CComPtr<IUnknown> m_pUnkMarshaler;
BEGIN_COM_MAP(..)
...
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
END_COM_MAP()
2) 在 FinalConstruct() 中創建編組器
FinalConstruct()
{
HRESULT rval = CoCreateFreeThreadedMarshaler( GetControllingUnknown(), &m_pUnkMarshaler.p );
...
}
FinalRelease()
{ ...; m_pUnkMarshaler = 0; }
3) 從 IConnectionPointImplMT 派生您的連接點,並在您可以同時觸發多個調用時在內部鎖定調用。
4) 不要在對象的方法中無限期地等待,因為您可能會陷入死鎖。
5) 對每個暴露的對象和連接點重復此操作。
(這應該有效,但我很久沒試過了......)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.