C# VSTO:在Excel主线程上调用

C# VSTO:在Excel主线程上调用,c#,excel,vsto,C#,Excel,Vsto,我在Excel工作表上有一个按钮,它启动一个新线程进行一些处理。如果我想对Excel进行任何更改(例如,使用工作表.Range(“A1”).Value=“info”)将数据写入单元格),我想我必须使用主UI线程 如何做到这一点 通常在Winforms中,我会在控件上调用Invoke,但是Excel.Application或工作表或范围对象没有Invoke方法。您是否尝试过从按钮启动BackgroundWorker?这使得它非常容易,因为ProgressChanged和RunWorkerCompl

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

如何做到这一点


通常在Winforms中,我会在控件上调用
Invoke
,但是
Excel.Application
工作表
范围
对象没有
Invoke
方法。

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


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

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

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

Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;
然后添加:

public Dispatcher Dispatcher { get {return _dispatcher;} }
然后,您可以通过

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

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

这是我使用WindowsForms为VSTO加载项提供的解决方案。 您不需要任何System.Windows.Forms.Control来使用它:


在此类中初始化addin:

        Globals.ThisAddIn.TheWindowsFormsSynchronizationContext.Send(d =>
        {
            MyMethodToInvoke();
        }, null);   
将此行添加到“ThisAddIn_启动”函数:

this.TheWindowsFormsSynchronizationContext = WindowsFormsSynchronizationContext.Current 
                                           ?? new WindowsFormsSynchronizationContext();
添加此新属性:

public SynchronizationContext TheWindowsFormsSynchronizationContext { get; private set; }

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

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

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

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


希望有帮助,Jörg

回答得很好。我一直在为类似的东西(xll插件)把头撞在墙上,这就解决了问题。正如您所说,虽然工作不需要在UI线程上完成,但如果您在另一个线程上完成,您可能会发现Excel.exe在关闭应用程序后仍然挂在任务管理器中。对于任何对
Dispatcher
感到困惑的人,您必须添加对
WindowBase
的引用才能访问
Dispatcher
类。当从其他线程调用时,我遇到的问题是Excel经常很忙,并抛出COMException。这就解决了问题。@JakeGinnivan我在
VS2019
中使用你对我的
VSTO
项目的建议。您要求在加载项的加载事件中添加
\u dispatcher
变量声明。你是说在班级层面上申报吗?否则,属性声明
public Dispatcher{get{return{u Dispatcher;}}
无法识别
\u Dispatcher
,因为
VS2019
正在抱怨我的
VSTO
项目。如果我遗漏了什么,请告诉我。非常感谢!搜索了半个小时后,这是VSTO唯一可行的解决方案!SynchronizationContext似乎比Dispatcher更通用、更安全(可以从UI外部调用)。这里的VS-answer也适用于基于ExcelDna的插件。使用AutoOpen()函数初始化上下文,而不是此addin\u启动。