2012-08-10 34 views
0

我有了這個功能的Excel加載項類:當在線程中調用Excel函數時CastError?

public void testRibbon() 
{ 
    Excel.Workbook workbook = this.Application.ActiveWorkbook;  
    Excel.Worksheet activeSheet = workbook.Sheets[1]; 
    Excel.Range range = activeSheet.get_Range(JOB_ID_FIELD + HEADER_ROW, TOTAL_STATUS_PERCENTAGE_KEY_FIELD + (10 + 1).ToString()); 
    range.get_Range("C4").Value = "test Ribbon complete"; 
} 

在我添加了一個按鈕,按下時會調用testRibbon在一個線程功能區:

private void process_Click(object sender, RibbonControlEventArgs e) 
{ 
    Thread processThread = new Thread(delegate(){ 
     Globals.ExcelAddin.testRibbon(); 
    }); 
    processThread.Start(); 
} 

這將導致鑄造錯誤:

Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.Excel._Workbook'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{000208DA-0000-0000-C000-000000000046}' failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).

如果我不使用新線程,則不會發生轉換錯誤。

編輯:使用任務工廠試了,同樣的錯誤:

var task2 = Task.Factory.StartNew(
() => 
{ 
    Globals.BobStats.testRibbon(); 
}); 

回答

2

執行在Excel中使用多線程是沒有意義的,因爲Excel的COM接口基本上單線程(見article)。插件中可能會有進一步的限制。

然而,我不得不說,我真的不明白是什麼錯誤消息是想說。

1

我想此刻,你正在COMObject連接接口類型「工作簿」 ...它會自動創建一個新的非託管線程,當您啓動()時,它將與您的線程崩潰。爲了具體,當你創建線程對象將一些數據結構保存到共享內存並沒有採用入門(),所以線程不會在這個時候

+0

我不太確定我明白「並且沒有使用Start(),所以此時線程未執行」。無論如何,對這個問題適當的解決辦法是什麼? 'testRibbon()'將被一個長時間運行的函數取代,我不想捆綁excel UI,所以它必須在一個線程中。 – 2012-08-10 20:34:54

+1

而不是思考線程,你可以像使用任務一樣使用它。它將不會崩潰當您使用Task.Factory .... – 2012-08-10 20:39:26

+0

謝謝,我會研究。我是C#的新手,並沒有聽說過任務。 – 2012-08-10 20:47:08

1

當您使用工作線程的Excel接口方法時,方法調用需要編組爲,編組爲。換句話說,該調用需要從創建Application對象的線程中進行。在.NET GUI應用程序中使用Control.Invoke()或Dispatcher.Invoke()的想法與此相同。

爲了使這項工作,COM需要知道哪些參數是對方法,因此可以適當地複製它們。這是需要在.NET中進行等效反射的那種信息。這需要元數據,描述COM方法的元數據存儲在類型庫中。 Excel的類型庫作爲資源存儲在Excel.exe中。

查找類型庫是怎麼回事錯在這裏。此信息存儲在註冊表中,出於某種原因它會在您的計算機上損壞。遭受重擊的最可能的關鍵是HKLM\SOFTWARE\Classes\TypeLib\{00020813-0000-0000-C000-000000000046}\1.7\0\win32,儘管它取決於Office的確切版本。您可以從SysInternals的ProcMon實用程序獲得更多信息,您將看到您的程序正在搜索關鍵字。

這種不幸的事是很少侷限於一個關鍵。您需要再次讓機器健康並重新安裝Office。

哦,記住,代碼不實際工作線程上運行。這需要在該工作線程上創建Application對象,並在啓動之前調用SetApartmentState()使其成爲STA。

+0

啊,這可能是由於安裝了多個不同版本的辦公軟件造成的,其中一些安裝已經搞亂了,我將全部卸載並全新安裝。 – 2012-08-10 21:58:45