2011-04-06 183 views
15

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

这怎么办?

通常在我的WinForms会叫Invoke的控制,但Excel.ApplicationWorksheetRange对象不具有Invoke方法。

回答

22

这项工作并不需要在UI线程上完成,.net会封送你的呼叫,但是如果你从后台线程重复呼叫,你可能会遇到性能问题。

但具体回答你的问题,如果你有.NET 3.5,在您的外接负载事件补充一点:

​​

,然后添加:

public Dispatcher Dispatcher { get {return _dispatcher;} } 

然后,你可以派遣到UI线程去

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

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

+0

伟大的答案。我一直在墙上敲我的头像类似的东西(xll加载项),并将其排序。虽然工作并不需要在UI线程上完成,但是如果您在另一个线程上完成工作,您可能会发现在关闭应用程序后,Excel.exe仍然处于任务管理器中。 – 2012-12-07 02:10:28

+3

对于任何对Dispatcher感到困惑的人,你必须添加对WindowBase的引用才能访问Dispatcher类。 – dotNET 2015-12-07 15:29:34

+0

我从不同的线程调用时遇到的问题是Excel经常繁忙并抛出一个COMException异常。这解决了它。 – Laurent 2017-04-14 08:02:12

2

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

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

6

这是我使用WindowsForms的VSTO AddIn的解决方案。 你不需要任何System.Windows.Forms。控制使用它:在课堂上的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

+0

非常感谢!搜索半小时后,这是VSTO唯一的工作解决方案! – Pali 2016-02-09 14:22:41

相关问题