VSTO:在主 Excel 线程上调用

发布于 2024-10-30 18:27:48 字数 309 浏览 0 评论 0原文

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

这怎么能做到呢?

通常在 Winforms 中,我会在控件上调用 Invoke,但 Excel.ApplicationWorksheetRange 对象不会没有 Invoke 方法。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

濫情▎り 2024-11-06 18:27:48

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

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

Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;

然后添加:

public Dispatcher Dispatcher { get {return _dispatcher;} }

然后您可以通过以下方式分派到 UI 线程

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

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

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.

白首有我共你 2024-11-06 18:27:48

这是我使用 WindowsForms 的 VSTO AddIn 解决方案。
您不需要任何 System.Windows.Forms.Control 即可使用它:


在 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

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

我ぃ本無心為│何有愛 2024-11-06 18:27:48

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文