2010-12-22 33 views
1

我有一個使用System.Timers.Timer myTimer的Visual Studio加載項。
每N秒myTimer火災並執行該代碼:因爲這會從另一個線程調用我有時會收到這些錯誤之一如何從另一個線程正確訪問COM對象DTE2.Windows枚舉器?

foreach(Window window in DTE2.Windows) 
{ 
    TextDocument td = window.Document.Object("TextDocument") as TextDocument; 
    // do stuff with td... 
} 

  • QI爲IEnumVARIANT失敗的 非託管服務器。
    在EnvDTE.Windows.GetEnumerator()
    上線的foreach(在DTE2.Windows窗口窗口)

  • 的應用程序調用的接口 這是編組爲不同 線程。 (從HRESULT異常: 0x8001010E(RPC_E_WRONG_THREAD))
    在EnvDTE.Window.get_Document()上線TextDocument TD = window.Document.Object( 「TextDocument」) 作爲TextDocument
    ;

什麼是訪問此枚舉在另一個線程,因爲COM對象所涉及的正確方法?
某種COM線程編組?
還有別的嗎?

+0

你是說,每次定時器觸發時,代碼段從不同的線程調用? – 2010-12-22 14:19:06

+0

是的。它會被調用System.Timers.Timer後臺線程,因爲它應該。 – 2010-12-22 14:27:35

回答

2

您正在運行COM,試圖保護不是線程安全的對象模型。像Visual Studio自動化界面這樣複雜的對象模型永遠都不會。 COM嘗試通過自動將後臺線程上的調用封送到STA線程來完成此操作。這是通過代理來完成的,原始COM接口的副本具有所有相同的方法,但將對它們的調用封送到在STA線程上運行方法的接口。

此代理具有線程關聯性,它只能在創建它的線程上使用。 DTE2是你的問題在這裏。如果任何可擴展性代碼在之前運行並創建了DTE2接口實例,則DTE2將成爲「真實」接口指針,而不是代理。如果您隨後在工作線程上使用它,就像Timer爲其Elapsed事件創建的那個一樣,那麼您將獲得炸彈。它也適用於其他方式,如果DTE2是由您的代碼首先創建的,那麼您將會轟炸以正常方式運行的任何擴展性代碼。

也許DTE2.DTE會解決你的問題,不確定。最終它不能解決任何問題,代碼總是要在Visual Studio STA線程上運行。只是不要使用System.Timer.Timer,使用像System.Windows.Forms.Timer同步計時器