开发者

VSTO: invoking on main Excel thread

I have a button on an Excel sheet which starts a new thread to do s开发者_开发知识库ome 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.


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.


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜