2011-02-24 83 views
1

我正在寫(並教我自己如何編寫)VB.NET 3.5中的實驗程序集,該程序集通過COM公開,然後從某些Excel VBA代碼調用以啓動實例該類捕獲一些Excel事件,然後在Excel中的活動工作簿上執行一些功能。.NET COM程序集通過BackgroundWorker與Excel交互

要啓動該類,將從VBA傳遞對Excel應用程序的引用(我在程序集中使用PIA for Excel)。

我需要在我的程序集上對活動工作簿執行耗時的操作,因此我決定在WinForm中使用BackgroundWorker,以便在操作在後臺完成時顯示進度對話框。

我想知道是否有任何問題與COM通過COM使用後臺工作人員以這種方式進行交互?詢問的原因是程序集中的主類保存對Excel應用程序對象的引用,然後傳遞給BackgroundWorker,以便它可以確定活動工作簿並對其執行一些操作。我只通過一個過程訪問工作簿本身(而不是其他對象)。

由於某種原因,我在我的腦海裏認爲Excel可能不會這樣 - 我說得對嗎?

+0

有幾張投票結束;我不明白爲什麼這不是一個「真正的問題」。提問者問是否合法或者是一個bug:「[是]那裏......用這種方式使用後臺工作者通過COM與Excel交互的任何問題[?]」 –

+0

是的,你是對的,有沒有問題,還是有更好的與Excel交互的方式? 也許我應該更好地表達這個問題......! –

回答

2

如果你指的是:

  • 充分利用VBA的方法調用你的VB.NET代碼
  • 分拆一個新的線程(或工作線程),並移交給一個參考工作簿(或Excel.Application,Range;無所謂)(通過參數,靜態...無關緊要)
  • 使用原始線程在後臺線程訪問Excel時顯示UI

然後,不;你不能這樣做。

Excel VBA是一個STA環境。所有對Excel對象模型的訪問都必須來自同一個線程。你也不會去挑選線索;它必須是調用你的方法開始的線程。

要運行代碼從工作線程訪問Excel,您必須將接口指針「封送」到工作線程。 Mashalling創建了一對COM包裝(稱爲'代理/存根'對),根據需要跨線程穿梭方法調用 - 這與您在.NET中使用Form.Invoke()方法時發生的情況類似。我不知道如何在.NET中做到這一點。無論如何,這不會是我的第一步。

另一種替代方法是不從工作線程訪問Excel對象,而是在主窗體對象中使用助手(您確實需要一個窗體,不是嗎?)。讓你的工作者線程通過Form.Invoke()調用這些幫助器,以確保它們從UI線程(VBA用來呼叫你的線程)運行。這在功能上與第一種選擇相同,不同之處在於.NET完成了工作,而不是COM。

第三種方法是根本不使用工作線程 - 使用VB方式:從唯一的線程創建UI;展示它,然後從表單的Load事件中完成您的工作。偶爾撥打Application.DoEvents()(每秒幾次)讓UI以平滑度的方式運行。

第四種選擇是解決問題。使用全新的線程而不是池線程(這是您從BackgroundWorker得到的)並從那裏處理UI。我們在這裏反轉角色:主線程會做花哨的工作,而額外的線程創建一個表單並顯示UI。再次確保您使用Form.Invoke()來更新進度窗口。當你完成後,確保你的線程已經完成Dispose()。這可能只是我的首選方法。

或者只是使用沙漏鼠標指針......你的「慢」是多麼「慢」?

+0

優秀!非常感謝建議,它讓我想到了:) –

0

對使用​​BackgroundWorker不太瞭解。我曾參與過一個Winforms應用程序,該應用程序通過PIA和COM連接到Excel。它使用一個普通的舊ThreadStart委託來啓動一個顯示進度條的線程,同時在後臺加載文件。工作很好。據我瞭解,BackgroundWorker在封面下工作非常類似,所以我會說去做。