ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 7797|回复: 2

[求助] 使用timeSetEvent写的计时器,可以启动多个同时计时

[复制链接]

TA的精华主题

TA的得分主题

发表于 2012-8-17 03:34 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:Windows API应用
本帖最后由 liucqa 于 2012-11-17 16:08 编辑

timeSetEvent与Settimer的区别是前者是内核模式在新的线程上工作,timeSetEvent会生成一个独立的Timer回调线程。
Settimer为用户模式,性能会好些?

在timeSetEvent调用中设置定时器回调函数时要遵循其规则,即回调函数的定义要严格遵照MSDN中的格式,而且在回调函数中除了PostMessage、timeGetSystemTime、timeGetTime、timeSetEvent、timeKillEvent、midiOutShortMsg、midiOutLongMsg、OutputDebugString几个函数外,不能调用其他Windows API函数,否则易造成系统出错甚至崩溃,故在实际运用中,使用要特别小心。



Option Explicit

Public Declare Function timeSetEvent Lib "winmm.dll" (ByVal uDelay As Long, ByVal uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, ByVal uFlags As Long) As Long
Public Declare Function timeKillEvent Lib "winmm.dll" (ByVal uID As Long) As Long

Public Declare Function Beep Lib "kernel32.dll" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long

Public lTimeID As Integer
Public lTimeID2 As Integer

Public n&, m&
Public busy1 As Boolean
Public busy2 As Boolean

'timeSetEvent (ByVal uDelay As Long, ByVal uResolution As Long, ByVal lpFunction As Long, ByVal dwUser As Long, ByVal uFlags As Long) As Long

'该函数的参数说明如下:
'参数uDelay表示延迟时间;
'参数uResolution表示时间精度,在Windows中缺省值为1ms;
'参数lpFunction表示回调函数,为用户自定义函数,定时调用;
'参数dwUser表示用户提供的回调数据;
'参数uFlags为定时器的事件类型,TIME_ONESHOT=0表示执行一次;TIME_PERIODIC=1:周期性执行。
'具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在lpTimeProc回调函数中,从而完成所需处理的事件?
'特别需要注意的是:  任务处理的时间不能大于周期间隔时间?!!
'另外,在定时器使用完毕后,应及时调用timeKillEvent()将之释放。

Public Sub startATimer()
    busy1 = False
    busy2 = False
    lTimeID2 = timeSetEvent(2000, 1, AddressOf TimeProc, 1, 1)      '注意定时器的时间要长于回调函数的执行时间
    If lTimeID2 = 0 Then
        MsgBox "cannot excute timesetevent2"
    End If
    lTimeID = timeSetEvent(3000, 0, AddressOf TimeProcAcq, 1, 1)    '如果短了会造成后继的代码无法执行,例如启动第二个计时器或者终止计时器
    If lTimeID = 0 Then
        MsgBox "cannot excute timesetevent"
    End If
End Sub

Sub TimeProcAcq(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, ByVal dw1 As Long, ByVal dw2 As Long)   '回调函数的固定格式,不能自行更改,且只能是sub
    If busy1 Then Exit Sub
    busy1 = True
    Beep 659, 200
    m = m + 1
    [a2] = Timer & "|" & uID & "|" & uMsg & "|" & dwUser & "|" & dw1 & "|" & dw2
    busy1 = False
End Sub

Sub TimeProc(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, ByVal dw1 As Long, ByVal dw2 As Long)
    If busy2 Then Exit Sub
    busy2 = True
    Beep 1059, 200
    n = n + 1
    [a1] = Timer & "|" & uID & "|" & uMsg & "|" & dwUser & "|" & dw1 & "|" & dw2
    busy2 = False
End Sub

Public Sub stopSTimer()
    If lTimeID Then timeKillEvent (lTimeID)
    If lTimeID2 Then timeKillEvent (lTimeID2)
    Exit Sub
End Sub



使用多媒体定时器应遵循以下3个步骤:  

1.   确定最大和最小周期  

可以用timeGetDevCaps函数确定多媒体定时器服务提供的最大和最小定时器事件周期,这些数值对不同的计算机是不同的,也与Windows运行方式有关。  

2.   建立最小定时器精度  

在启动定时器事件前,应用程序必须建立想要使用的最小定时器精度,在定时器服务事件结束之后,还必须清除该精度。  

最小定时器精度可以根据第一步返回的结果确定。可以使用timeBeginPeriod和timeEndPeriod函数来设置和清除最小定时器精度,每个timeBeginPeriod调用都必须有一个timeEndPeriod与之对应,而且两个函数必须指定相同的最小精度。  

3.   启动定时器事件  

与该步骤相关的两个函数为timeSetEvent和timeKillEvent,详细细节可以查阅MSDN中这两个函数的定义。有三个要注意的地方:
一是一旦启动定时器就一定不要忘记把它关闭,因为小于100毫秒的定时器对CPU   的消耗是非常大的,而且下次启动定时器会造成多个定时器同时运行,使得数据采集的结果是错误的;
二是在timeSetEvent调用中设置定时器回调函数时要遵循其规则,即回调函数的定义要严格遵照MSDN中的格式,而且在回调函数中除了PostMessage、timeGetSystemTime、timeGetTime、timeSetEvent、timeKillEvent、midiOutShortMsg、midiOutLongMsg、OutputDebugString几个函数外,不能调用其他Windows   API函数,否则易造成系统出错甚至崩溃;
三是回调函数应编写得短小精悍,因为定时器事件发生的周期非常短,程序很长会造成延时,影响数据采集的实时性。

TA的精华主题

TA的得分主题

发表于 2012-8-17 08:10 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
timeSetEvent理论上中断时间更为精确,SetTimer因为使用的是窗体消息,延时可能比较严重。
但是timeSetEvent对时钟处理过程要求比较严格,但是这有个很大的问题,因为VBA是解释执行的,运行速度非常之慢,如果设置的时钟间隔比较短,那就得不偿失了。
一般来说,普通应用的时钟用SetTimer就可以了。毕竟要求精确度要求到毫秒级的时钟还是比较少。。。

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-8-17 08:30 | 显示全部楼层
joforn 发表于 2012-8-17 08:10
timeSetEvent理论上中断时间更为精确,SetTimer因为使用的是窗体消息,延时可能比较严重。
但是timeSetEve ...

嗯,有道理,我就是闲得没事,想看看vba里面能不能用timeSetEvent。

调试下来,发现果然限制很多。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-26 18:06 , Processed in 0.033901 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表