VSTO:在主Excel线程上调用

Lau*_*ent 20 c# excel vsto

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

如何才能做到这一点?

通常,在的WinForms我所说Invoke的控制,但Excel.ApplicationWorksheetRange对象没有一个Invoke方法.

Jak*_*van 27

这项工作并不需要在UI线程上完成,.net将为您编组调用,但如果您从后台线程重复调用,则可能会遇到性能问题.

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

Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;
Run Code Online (Sandbox Code Playgroud)

然后添加:

public Dispatcher Dispatcher { get {return _dispatcher;} }
Run Code Online (Sandbox Code Playgroud)

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

Globals.ThisAddIn.Dispatcher.Invoke(()=>{/*stuff*/});
Run Code Online (Sandbox Code Playgroud)

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

  • 对于其他对"Dispatcher"感到困惑的人,你必须添加对`WindowBase`的引用才能访问`Dispatcher`类. (6认同)

jre*_*ert 11

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


类ThisAddIn中的初始化:

将此行添加到"ThisAddIn_Startup"函数:

this.TheWindowsFormsSynchronizationContext = WindowsFormsSynchronizationContext.Current 
                                           ?? new WindowsFormsSynchronizationContext();
Run Code Online (Sandbox Code Playgroud)

添加这个新属性:

public SynchronizationContext TheWindowsFormsSynchronizationContext { get; private set; }
Run Code Online (Sandbox Code Playgroud)

然后工作线程中的用法是:

        Globals.ThisAddIn.TheWindowsFormsSynchronizationContext.Send(d =>
        {
            MyMethodToInvoke();
        }, null);   
Run Code Online (Sandbox Code Playgroud)

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

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

希望它有所帮助,Jörg