2009-08-05 72 views
18

的COM對象,我有以下代碼:無法投類型的異常

public void Test(IMyInterface iInterface) 
{ 
    iInterface.CallMethod (); 
} 

工作正常。但是,如果我更改代碼以被擰:

private IMyInterface myInterface; 
public void Test(IMyInterface iInterface) 
{ 
    myInterface = iInterface; 
    new Thread (new ThreadStart (CallInterfaceMethod)).Start (); 
} 

public void CallInterfaceMethod () 
{ 
    myInterface.CallMethod () 
} 

當我使用線程我收到異常:

無法轉換類型的COM對象「系統.__ ComObject」到接口類型「IMyInterface的」 。 此操作失敗,因爲IID爲{{GUID}的接口的COM組件上的QueryInterface調用失敗,原因如下錯誤:沒有此類接口支持

但接口應該支持就好了嗎?任何人對這裏發生的事情有任何想法?

+0

http://blogs.msdn.com/b/oldnewthing/archive/2004/12/13/281910.aspx – EricLaw 2015-10-20 18:20:08

回答

20

這個令人討厭的,令人討厭的異常出現,因爲一個稱爲COM編組的概念。問題的實質在於,爲了從任何線程中使用COM對象,線程必須有權訪問描述COM對象的類型信息。

在你描述的場景中,它在第二個線程上失敗的原因是因爲第二個線程沒有接口的類型信息。

你可以嘗試加入以下代碼:

[ComImport] 
[Guid("23EB4AF8-BE9C-4b49-B3A4-24F4FF657B27")] 
public interface IMyInterface 
{ 
    void CallMethod(); 
} 

基本上宣告上述指示.NET框架COM加載使用傳統技術從註冊表加載類型信息,並找到相關的類型庫,並去從那裏。

您還應該將COM對象的創建限制爲單個線程(以防止線程編組)以幫助解決此問題。

總之,這個錯誤圍繞着類型信息和線程編組。確保每個想要訪問COM對象的線程都具有相關信息,以便從源線程解組對象。

PS:這個問題在.NET 4中解決。0使用稱爲「類型對等」的技術

+0

感謝您的回覆。您的探索是有道理的,並且在MSDN上查找ComImport的刪減似乎也是有道理的。乾杯。 – Kyle 2009-08-11 12:21:27

+0

這是我的榮幸:)我之前遇到過這個問題,這是一個噩夢,試圖解決,直到燈泡熄滅,並最終從創建它的線程中消耗COM對象。 – 2009-08-11 12:58:58

+1

[+1]非常感謝你們!對我來說,錯誤是[STAThread]丟失。這個問題和答案讓我在閱讀線程問題後找到它。 – Marc 2010-08-19 07:26:19

-1

好吧,其中之一,你是一個跨線程調用對象而不鎖定它,這會自動導致一些問題。你的代碼應該看起來更像是:

private IMyInterface myInterface; 
private static readonly object _myObjectLock = new object(); 

public void Test(IMyInterface iInterface) 
{ 
    myInterface = iInterface; 
    new Thread (new ThreadStart (CallInterfaceMethod)).Start (); 
} 

public void CallInterfaceMethod () 
{ 
    lock(_myObjectLock) 
    { 
     myInterface.CallMethod (); 
    } 
} 

據我所知,你上市的時候,資源不能被訪問,有時會出現錯誤,它與這樣的跨線程操作,最有可能發生的。不過,不要引用我的話,我不是COM專家。

說實話,我不認爲我會用這種方式來調用這個方法,這樣做的風險太多了。您是否考慮過使用ParameterizedThreadStart並通過該方式傳遞對象?您仍然需要安全地鎖定對象以進行跨線程操作,但它會更安全。

此外,請檢查以確保您的「myInterface」類仍然可以調用「CallMethod()」方法。接口沒有實現,當你設置「myInterface = iInterface」時,你可能會遇到問題。

+0

比你的答案,但使用ParameterizedThreadStart無效(有或沒有鎖)。 另外我也檢查過,myInterface在設置好後仍然可以「調用方法」(myInterface = iInterface)。 – Kyle 2009-08-06 14:30:49

+0

在這個答案中有兩點錯誤信息:** 1。**跨線程對象訪問不會總是自動導致問題。例如,對於只讀訪問,鎖定不是必需的。 ** 2。**關於最後一段,您不能將對象作爲對象傳遞,所以即使您將一個非null對象指定給具有接口(靜態)類型的變量,並且代碼也會編譯,那麼所有這些方法都可以叫做。將靜態類型(接口)視爲另一種實現類型的某種外觀。 – stakx 2012-07-13 09:19:09

3

我得到了一個建議,它幫助了我!

在主線程(Program.cs)中找到[STAThread]行並將其更改爲[MTAThread]。

+0

它像一個魅力工作。請你解釋一下這個變化嗎? – 2016-12-21 12:21:07

0

我一直在開發一個C#應用程序,它通過COM接口使用7-zip。我遇到了這樣一個有趣的事情,我可以在一個實例中從工作線程中提取歸檔文件,但不是另一個,得到相同的異常。

我發現,只要您在使用它的線程中初始化有問題的COM對象,不會引發異常。我的解決方案是處理使用COM接口的對象,並在線程之間傳遞對象時重新初始化它們。

相關問題