【发布时间】:2011-08-05 18:12:02
【问题描述】:
我已投入大量时间将一些旧的 VB6 / *.xla 代码转换为 C# 应用程序,现在我发现自己陷入了一个重大的性能漏洞。从 C# (VS 2010) 自动化 Excel 似乎会对性能产生某种重大影响。我在测试 VB6 应用程序中编写了“精确”代码,并在大约 1-2 秒内运行计算。因为 C# 中的代码需要一分钟。代码的一般流程是这样的……(其中客户端是 VB6 或 C# 应用程序)。
-- 在客户端应用程序的生命周期内只执行一次
客户端创建并打开 Excel 应用程序
-
客户端使 Excel 自动加载计算所需的加载项。
-- 为执行的每个计算完成
客户端使 Excel 自动关闭任何现有的 *.xls 文件并打开所需的 *.xls 文件。
客户端使用 ExcelAppObject.Run("AddIn.xla!GetConfiguration") 从 Excel 调用宏添加以获取在步骤 3 中打开的 *.xls 的配置。
-
客户端从 Excel 调用宏,使用 ExcelAppObject.Run("AddIn.xla!LoadInputs", InputsXmlString)
- 宏将 InputsXmlString 加载到 MSXML.DOMDocument40 对象中。
- 宏将 Application.Calculation = xlCalculationManual(以加快填充多个输入“表”的速度)
- 宏设置 Application.EnableEvents = false
- 宏循环“输入”工作表上的所有“已配置”输入/表并清除它们(以防传入的 xml 不包含“所有”输入)
- 宏循环所有传入的 xml 并加载到“输入”工作表上的适当位置。
-
客户端从 Excel 调用宏,使用 ExcelAppObject.Run("AddIn.xla!GetResults", DataXmlString)
- 宏将 DataXmlString 加载到 MSXML.DOMDocument40 对象中。
- 宏循环“输入”工作表上的所有“配置”数据值并清除它们(以防传入的 xml 不包含“所有”数据或清除之前的计算)
这与 LoadInputs 不同,因为我们可以进行批量计算,其中每次计算的输入都相同,但每次计算的“参与者数据”显然不同 - 宏将 DataXmlString 中的所有数据加载到“输入”工作表上的适当位置
- 宏设置 Application.EnableEvents = true
- 宏将 Application.Calculation = xlCalculationAutomatic(以确保在所有数据/输入都已加载后进行计算)
- 宏循环所有已配置的“结果单元格”并通过 Xml 字符串返回。
如您所见,对于每个计算,我只有三个从客户端到 Excel 的“跨进程”调用(GetConfiguration、LoadInputs 和 GetResults)来尝试最小化已知的“差”性能问题。问题是,当从 VB6 应用程序中调用完全相同的代码时,步骤 4-6 大约需要 2 秒。当客户端应用程序是 C# 应用程序时,4-6 大约需要 70 秒。 所有这 70 秒都发生在第 6 步,当我将计算转回自动时。
相对于旧版 VB6 应用程序,C# 应用程序自动化 Excel 是否存在已知问题和/或是否有任何建议的变通方法,以便我可以保留 C# 代码但以某种方式实现与 VB6 相同的性能?
【问题讨论】:
-
尝试在发布模式下构建您的应用程序并在 Visual Studio 之外运行它。
-
我们是/已经内置发布。然后开始调试和发现问题,我们现在在 LINQPad 中使用“更简单”更直接的脚本而不是我们的整个“代理”代码/框架进行测试。
-
所以你试过在不附加任何调试器的情况下运行它?
标签: c# performance excel vb6 automation