VSTO:在主Excel线程上调用

我有一个Excel工作表上的button,启动一个新的线程做一些处理。 如果我想对Excel进行任何更改(例如使用Worksheet.Range("A1").Value = "info"; )将数据写入单元格,我想我必须使用主UI线程。

如何才能做到这一点?

通常在Winforms中,我将在控件上调用Invoke ,但Excel.ApplicationWorksheetRange对象没有Invoke方法。

这个工作并不需要在UI线程上完成,.net会为你调用这个调用,但是如果你从后台线程重复调用,你可能会遇到性能问题。

但是要专门回答您的问题,如果您有.net 3.5,请在您的加载项加载事件中添加以下内容:

 _dispatcher = Dispatcher.CurrentDispatcher; 

然后添加:

 public Dispatcher Dispatcher { get {return _dispatcher;} } 

然后你可以通过去调度到UI线程

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

如果您没有.net 3.5,那么还有一些其他线程同步技术,如使用SynchronizationContext.Current而不是Dispatcher。

这是我使用WindowsForms的VSTO AddIn的解决scheme。 你不需要任何System.Windows.Forms.Control来使用它:


在类ThisAddIn中初始化:

将此行添加到“ThisAddIn_Startup”函数中:

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

添加这个新的属性:

 public SynchronizationContext TheWindowsFormsSynchronizationContext { get; private set; } 

那么工作线程中的用法是:

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

第二个解决scheme(未testing):你也可以使用:

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

Jörg,希望有帮助

你有没有尝试从你的button开始BackgroundWorker? 这使得它非常容易,因为ProgressChanged和RunWorkerCompleted事件将在主线程上触发。

我还没有在Excel / VSTO环境中尝试过,但我不明白为什么它不起作用。