gpt4 book ai didi

multithreading - 从 VBA 调用计算密集型例程而不停止 Excel GUI

转载 作者:行者123 更新时间:2023-12-02 02:15:58 25 4
gpt4 key购买 nike

我有一组数字密集型例程(每个例程最多需要 1 分钟才能完成),它们捆绑在 COM 对象中,干净地实现了 IDispatch

因此,我可以从 Excel 工作表中使用它们,这些例程将由按钮触发的 VBA 宏调用。

现在,当调用这些例程之一时,Excel 用户界面就会卡住,这对于工作表的最终用户来说非常不舒服。

我想找到任何机制来缓解这个问题。

这可能是例如在 COM 端启动的另一个线程中启动计算,立即返回,生成的线程在计算结果时回调 VBA 过程。

或者更简单的东西,因为我一次只需要执行一项计算。

现在,从其他线程调用 VBA 例程可能会出现很多问题。我必须承认我对 COM 没有那么丰富的经验,我只是将其视为代码和 Excel 之间的黑匣子(我使用 ATL)。

所以,

是否可以从另一个线程回调 VBA 例程?

有更好的方法来实现我想要实现的目标吗?

更新

在权衡各种选择并阅读互联网上的大量内容之后,我将进行协作多线程处理:在 COM 对象中,我将拥有三个例程,而不是一个例程:

class CMyObject : ...
{
...

STDMETHOD(ComputationLaunch)(...); // Spawn a thread and return immediately
STDMETHOD(ComputationQuery)(DOUBLE* progress, BOOL* finished);
STDMETHOD(ComputationResult)(VARIANT* out);

private:
bool finished, progress;
boost::mutex finished_lock, progress_lock;
ResultObject result; // This will be marshaled to out
// when calling ComputationResult
};

在 VBA 中:

Private computeActive as Boolean ' Poor man's lock

Public Sub Compute()

OnError GoTo ErrHandler:

If computeActive Then Exit Sub
computeActive = True

Dim o as MyObject
call o.ComputationLaunch

Dim finished as Boolean, progress as Double

While Not o.ComputationQuery(progress)
DoEvents
' Good place also to update a progress display
End While

Dim result as Variant
result = o.ComputationResult

' Do Something with result (eg. display it somewhere)

computeActive = False
Exit Sub

ErrHandler:
computeActive = False
Call HandleErrors

End Sub

事实上,通过在 Internet 上对 COM 加载项进行深度优先搜索,我意识到 VBA 宏在与 Excel 的 GUI 相同的事件循环中运行,您拥有 DoEvents 工具,并且从其他线程回调 VBA 过程安全(或者至少非常棘手)。这需要例如。欺骗辅助功能来获取 Excel.Application 对象的同步句柄,并调用 OnTime 方法来设置异步事件处理程序。不值得这么麻烦。

最佳答案

如果你想做好这件事,你需要放弃 VBA 并编写 COM 加载项。

关于multithreading - 从 VBA 调用计算密集型例程而不停止 Excel GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5748262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com