VSTO:在主Excel线程上调用

时间:2011-04-06 14:18:32

标签: c# excel vsto

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

如何做到这一点?

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

3 个答案:

答案 0 :(得分:25)

这项工作不需要在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。

答案 1 :(得分:9)

这是我使用WindowsForms的VSTO AddIn的解决方案。 您不需要任何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);   

第二种解决方案(未经测试):您也可以使用:

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

希望它有所帮助,Jörg

答案 2 :(得分:2)

您是否尝试过按钮启动BackgroundWorker?这使得它很容易,因为ProgressChanged和RunWorkerCompleted事件将在主线程上触发。

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