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

我正在写一个VB.NET 3.5中的实验程序集,并通过COM公开,然后从一些Excel VBA代码调用来启动一个类的实例,该类捕获一些Excel事件,然后执行一些functionExcel中的活动工作簿。

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

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

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

由于某种原因,我的脑海里,Excel可能不会这样 – 我说得对吗?

如果你是指这个:

  • 从VBA获取方法调用到您的VB.NET代码
  • 分离一个新的线程(或一个工作线程),并交给工作簿(或Excel.Application,一个范围的参考;这并不重要)(通过参数,静态…没关系)
  • 当后台线程访问Excel时,使用原始线程显示UI

那就不要; 你不能这样做。

Excel VBA是一个STA环境。 所有对Excel对象模型的访问都必须来自同一个线程。 你也不会去挑选线索; 它必须是调用你的方法开始的线程。

要从工作线程运行访问Excel的代码,必须将接口指针“封送”到工作线程。 Mashalling创build了一对COM包装(称为“代理/存根”对),根据需要Form.Invoke()线程穿梭方法调用 – 这与您在.NET中使用Form.Invoke()方法时发生的情况类似。 我不知道如何在.NET中做到这一点。 这不会是我的第一个方法。

另一种select是不从工作线程访问Excel对象,而是在主窗体对象中使用助手(你确实需要一个窗体,不是吗?)。 让你的工作者线程通过Form.Invoke()来调用这些帮助器,以确保他们从UI线程(VBA用来调用你的线程)运行。 这在function上与第一个select相同,不同之处在于.net执行工作,而不是COM。

第三种方法是根本不使用工作线程 – 使用VB方法:从唯一的线程创build您的UI; 展示它,然后从Form的Load事件中完成你的工作。 调用Application.DoEvents()偶尔(每秒几次)让UI以平滑的方式运行。

第四个select是围绕这个问题。 使用一个全新的线程而不是一个池线程(这是你从BackgroundWorker获得的),并从那里处理UI。 我们在这里反转angular色:主线程将做花哨的工作,而额外的线程创build一个窗体并显示UI。 再次确保您使用Form.Invoke()来更新进度窗口。 确保完成后Dispose()线程。 这可能只是我的首选方法。

或者只是使用一个沙漏鼠标指针…只是“慢”是你的“慢”?

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