【发布时间】:2010-06-09 17:21:59
【问题描述】:
我需要一种比 user32.dll 中的 SetTimer API 更好的引发事件的方法。
您是否成功使用过其他定时器 API?您知道在 Excel 中引发事件或异步调用函数的另一种方法吗?
“更好”是什么意思?我需要一些可以从内部维护的队列中异步弹出消息的东西。问题是外部数据源(路透社市场数据)将项目推送到队列中,该数据源使用 WM_Application 范围内的消息引发其“数据更新”事件; SetTimer 的工作原理是发送 WM_Timer 消息,这是 Windows 消息的七石弱点,我的“Pop”进程永远没有机会运行,即使在相对较少的流量中也是如此。
如果您对更好的架构有任何建议,请随时提出:但传入的数据更新事件绝对必须尽快进入事件“接收器” - 如果事件(或回调)过多,Excel 将崩溃在一些漫长而缓慢的过程正在处理最后一个事件以及之前的事件时引发。我的队列的大小是有限的,因为应用程序中只有几百只股票:传入的数据更新可以查看和更新现有项目,如果它是已经在队列中的股票的更新价格,或者推送新股票的股票代码和价格进入队列。因此,从来没有因为我们很忙而丢失任何定价数据,并且对 push 和 peek 函数的简洁编码意味着事件接收器足够快以确保 Excel 保持稳定。
但我一直在寻找一种更好的方式将项目从队列中弹出。
不幸的是,我尝试过的所有其他计时器 API 似乎都不能在 VBA 中工作:它们会使应用程序崩溃或冻结代码执行。这是列表(超链接指向 MSDN 文档):
- CreateTimerQueueTimer Lib "Kernel32.dll"
- CreateWaitableTimer 库“kernel32”
- TimeSetEvent 库“winmm.dll”
我怀疑我在使用这些函数时遇到的问题与我的语法错误无关:我不太了解 Windows 线程模型,无法说出它们回调时实际发生的情况,但是关于一个其中声明“此回调函数不得调用 TerminateThread 函数”,我认为这意味着 VBA 不能“接收”使用该特定计时器 API 引发的事件。
认为我知道正确的 API 调用来杀死或删除这些计时器及其相关队列:空间有限,可等待计时器使用单独的 Create-、Set-、Cancel- 和 CloseHandle API 调用。 TimerProc 函数的签名都略有不同。
这是标准的 SetTimer 函数调用:
lngTimerID = SetTimer(hWndXL, VBA.ObjPtr(Me), lngInterval, AddressOf TimerProc)
我不会用 TimerProc 函数声明和关于委托的题外话来烦你:如果你能回答这个问题,你已经看过所有相关的代码示例了。
期待您的回复:我有一个正在运行的应用程序,仔细编码和隔离意味着内部数据滞后是可以接受的。但我想我可以做得更好,即使我仅限于提供独立的 Excel 工作簿。
【问题讨论】:
-
很高兴看到这个问题在发布四年后仍然获得流量......但是,请在此处发布您自己的 cmets 和观察结果。除其他外,我认为至少有一个广泛发布的 64 位 TImerProc 调用的 API 声明是不正确的:但我对自己的编码并没有相当如此自信,以至于无法用代码与既定专家相矛盾样本,充其量是在包含新错误的意义上的改进。