2011-04-06 76 views
15

我在Excel工作表上有一個按鈕,它啓動一個新線程來做一些處理。如果我想對Excel進行任何更改(例如使用Worksheet.Range("A1").Value = "info";將數據寫入單元格),我想我必須使用主UI線程。VSTO:在主Excel線程上調用

這怎麼辦?

通常在我的WinForms會叫Invoke的控制,但Excel.ApplicationWorksheetRange對象不具有Invoke方法。

回答

22

這項工作並不需要在UI線程上完成,.net會封送你的呼叫,但是如果你從後臺線程重複呼叫,你可能會遇到性能問題。

但具體回答你的問題,如果你有.NET 3.5,在您的外接負載事件補充一點:

​​

,然後添加:

public Dispatcher Dispatcher { get {return _dispatcher;} } 

然後,你可以派遣到UI線程去

Globals.ThisAdd.Dispatcher.Invoke(()=>{/*stuff*/}); 

如果你沒有.net 3.5,那麼還有一些其他的線程同步如使用SynchronizationContext.Current而不是Dispatcher。

+0

偉大的答案。我一直在牆上敲我的頭像類似的東西(xll加載項),並將其排序。雖然工作並不需要在UI線程上完成,但是如果您在另一個線程上完成工作,您可能會發現在關閉應用程序後,Excel.exe仍然處於任務管理器中。 – 2012-12-07 02:10:28

+3

對於任何對Dispatcher感到困惑的人,你必須添加對WindowBase的引用才能訪問Dispatcher類。 – dotNET 2015-12-07 15:29:34

+0

我從不同的線程調用時遇到的問題是Excel經常繁忙併拋出一個COMException異常。這解決了它。 – Laurent 2017-04-14 08:02:12

2

您是否嘗試過從您的按鈕啓動BackgroundWorker?這使得它非常容易,因爲ProgressChanged和RunWorkerCompleted事件將在主線程上觸發。

我還沒有在Excel/VSTO環境中試過這個,但我不明白爲什麼它不起作用。

6

這是我使用WindowsForms的VSTO AddIn的解決方案。 你不需要任何System.Windows.Forms。控制使用它:在課堂上的ThisAddIn


初始化:

加入這一行 「ThisAddIn_Startup」 功能:

this.TheWindowsFormsSynchronizationContext = WindowsFormsSynchronizationContext.Current 
              ?? new WindowsFormsSynchronizationContext(); 

添加這個新屬性:

public SynchronizationContext TheWindowsFormsSynchronizationContext { get; private set; } 

然後在工作線程的用法是:

 Globals.ThisAddIn.TheWindowsFormsSynchronizationContext.Send(d => 
     { 
      MyMethodToInvoke(); 
     }, null); 

第二種解決方案(未測試):也許你可以同時使用:

 var invokerControl = new Control(); 
     invokerControl.CreateControl(); //Forces the control handle to be created 
     invokerControl.Invoke(new MethodInvoker(MyMethodToInvoke)); 

希望它有幫助,Jörg

+0

非常感謝!搜索半小時後,這是VSTO唯一的工作解決方案! – Pali 2016-02-09 14:22:41