VSTO: invoking on main Excel thread

扶醉桌前 提交于 2019-12-17 22:24:57

问题


I have a button on an Excel sheet which starts a new thread to do some processing. If I want to make any changes to Excel (e.g. write data to a cell using Worksheet.Range("A1").Value = "info";), I think I must use the main UI thread.

How can this be done?

Typically in Winforms I would call Invoke on a control, but the Excel.Application or Worksheet or Range objects don't have an Invoke method.


回答1:


That work doesn't 'need' to be done on the UI thread, .net will marshal the call for you, but if you make repeated calls from a background thread you may hit performance issues.

But to answer your question specifically, if you have .net 3.5, in your add-in load event add this:

Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;

And then add:

public Dispatcher Dispatcher { get {return _dispatcher;} }

Then you can dispatch to the UI thread by going

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

If you don't have .net 3.5, then there are a few other thread synchronisation techniques, like using SynchronizationContext.Current instead of the Dispatcher.




回答2:


This is my solution for a VSTO AddIn using WindowsForms. You don't need any System.Windows.Forms.Control to use it:


Initialization in class ThisAddIn:

Add this line to "ThisAddIn_Startup" function:

this.TheWindowsFormsSynchronizationContext = WindowsFormsSynchronizationContext.Current 
                                           ?? new WindowsFormsSynchronizationContext();

Add this new property:

public SynchronizationContext TheWindowsFormsSynchronizationContext { get; private set; }

Then the usage in the worker thread is:

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

A second solution (Not tested): You could maybe also use:

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

Hope it helps, Jörg




回答3:


Have you tried starting a BackgroundWorker from your button? This makes it very easy as the ProgressChanged and RunWorkerCompleted events will fire on the main thread.

I haven't tried this in an Excel/VSTO environment but I don't see why it wouldn't work.



来源:https://stackoverflow.com/questions/5567858/vsto-invoking-on-main-excel-thread

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!