.NET COM程序集通过BackgroundWorker与Excel交互

时间:2011-02-24 00:20:40

标签: .net vb.net excel com backgroundworker

我正在编写(并教自己如何编写)VB.NET 3.5中的实验程序集,它通过COM公开,然后从一些Excel VBA代码调用,以启动一个类的实例来捕获一些Excel事件,然后执行Excel中活动工作簿上的一些函数。

要启动该类,将从VBA传递对Excel应用程序的引用(我在程序集中使用PIA for Excel)。

我需要从我的程序集对活动工作簿执行耗时的操作,所以我决定在WinForm中使用BackgroundWorker,这样我就可以在操作完成时显示操作的进度对话框。背景

我想知道使用后台工作者以这种方式通过COM与Excel交互是否有任何问题?询问的原因是程序集中的主类保存对Excel应用程序对象的引用,然后将其传递给BackgroundWorker,以便它可以确定活动工作簿,然后对其执行某些操作。我只通过一个过程访问工作簿本身(而不是其他对象)。

出于某种原因,我觉得Excel可能不喜欢这样 - 我是对的吗?

2 个答案:

答案 0 :(得分:2)

如果你参考这个:

  • 从VBA获取方法调用VB.NET代码
  • 关闭一个新线程(或一个工作线程)并将一个引用移交给工作簿(或者Excel.Application,一个Range;它没关系)(通过参数,静态...它不会物质)
  • 在后台线程访问Excel时使用原始线程显示UI

然后,没有;你不能这样做。

Excel VBA是一个STA环境。所有对Excel对象模型的访问都必须在同一个线程中进行。你也没有选择线程;它必须是调用你的方法开始的线程。

要运行从工作线程访问Excel的代码,您必须“编组”指向工作线程的接口指针。 Mashalling创建了一对COM包装器(称为“代理/存根”对),可以根据需要在线程之间传递方法调用 - 这类似于在.NET中使用Form.Invoke()方法时发生的情况。我不知道如何在.NET中做到这一点。无论如何,这不是我的第一个方法。

另一种选择是不要从你的工作线程访问Excel对象,而是在主表单对象中使用帮助器(你确实需要一个表单,不是吗?)。让您的工作线程通过Form.Invoke()调用这些帮助程序,以确保它们从UI线程(VBA用来调用您的线程)运行。这在功能上与第一个替代方案相同,除了.NET完成工作,而不是COM。

第三种方法是根本不使用工作线程 - 以VB方式执行:从唯一的线程创建UI;显示它,然后从表单的Load事件中完成您的工作。偶尔呼叫Application.DoEvents()(每秒几次)让UI以平滑的一些相似性进行操作。

第四种选择是解决问题。使用全新的线程而不是池线程(这是从BackgroundWorker获得的)并从那里处理UI。我们在这里反转角色:主线程将执行奇特的工作,而额外的线程创建一个表单并显示UI。同样,请确保使用Form.Invoke()更新进度窗口。完成后确保你Dispose()你的线程。这可能只是我的首选方法。

或者只是使用沙漏鼠标指针......你的“慢”是多么“慢”?

答案 1 :(得分:0)

对使用BackgroundWorker不太了解。我曾经使用过通过PIA和COM连接到Excel的Winforms应用程序。它使用一个普通的旧ThreadStart委托来启动一个线程,该线程在后台加载文件时显示进度条。工作得很好。据我所知,BackgroundWorker在封面下的工作方式基本相同,所以我会说它去做。