我在Excel工作表上有一个按钮,它启动一个新线程来进行一些处理.如果我想对Excel进行任何更改(例如,将数据写入单元格Worksheet.Range("A1").Value = "info";),我想我必须使用主UI线程.
如何才能做到这一点?
通常,在的WinForms我所说Invoke的控制,但Excel.Application或Worksheet或Range对象没有一个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.
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