VSTO:在主Excel线程上调用
我有一个Excel工作表上的button,启动一个新的线程做一些处理。 如果我想对Excel进行任何更改(例如使用Worksheet.Range("A1").Value = "info";
)将数据写入单元格,我想我必须使用主UI线程。
如何才能做到这一点?
通常在Winforms中,我将在控件上调用Invoke
,但Excel.Application
或Worksheet
或Range
对象没有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环境中尝试过,但我不明白为什么它不起作用。