如果咋调用TimeDelay延时5秒的过程中按了command2,就产生什么情况?窗体卸载,但是窗体过程还在运行,矛盾了: 在ide里面,运行程序,command1后有输出,点了command2之后,程序没有终止,但是这个时候在ide里面暂停程序,会发现程序中止在TimeDelay过程里面.至少在TimeDelay里面循环的过程里面加上对退出状态的检查,以便能及时退出. Public Sub TimeDelay(delayMilliseconds As Long)没有写2个Timer的时间设置,如果两个Timer处理过程用了1秒,而timer是0.5秒触发一次,也会有问题.timer对象似乎不可重入,而已两个timer会互相影响. Option Explicit Dim bexit As Boolean Private Sub Form_Load() Debug.Print NUm & " Load me ..." NUm = NUm + 1 Open "c:\yw.txt" For Output As #1 '没有文件关闭的语句,程序结束后系统会自动写入文件,并且关闭文件 End SubPrivate Sub Timer1_Timer() 'Timer1.Interval=20'变态设置,在20ms循环根本不结束的. Dim i, j, a, b a = Timer For i = 1 To 1200 For j = 1 To 1200 b = j DoEvents 'If bexit = True Then Exit Sub Next Next Print #1, "Timer1 " & Timer, Timer - a End SubPrivate Sub Timer2_Timer() 'Timer1.Interval=30'变态设置,在30ms循环根本不结束的. Dim i, j, a, b b = Timer For i = 1 To 1200 For j = 1 To 1200 a = j DoEvents 'If bexit = True Then Exit Sub Next Next Print #1, "Timer2 " & Timer, Timer - b End Sub 输出文件Timer2 36721.02 1.609375 Timer2 36722.63 1.578125 Timer2 36724.23 1.578125 Timer2 36725.89 1.625 Timer2 36727.5 1.578125 Timer2 36729.22 1.6875 Timer1 36730.63 11.21875 timer1的运行受到了影响,编译和不编译都是受影响的
各位老师,我重新发我写的程序,完整的,请大家调试'此语句放在一个独立的 module 中 Public Declare Function GetTickCount Lib "kernel32" () As Long'以下都在窗体中,窗体包含 2个定时器,2个按钮,1个标签,1个文本矿 Private bIsExit As Boolean Private bIsWaiting As Boolean, bIsProcess As Boolean Private TimeLen As Integer '======================================================= '程序功能:点击开始 Command2 时,程序每隔5秒输出当前时间 '该程序问题:单击结束按钮 Command2 时无法结束 '=======================================================Public Sub TimeDelay(delayMilliseconds As Long) '----------------------- '为程序进行延时的子过程 'Do Until 条件.........loop '这个条件是为假才会执行 直到为真停止 '----------------------- On Error Resume Next
'此处加上程序退出判断 If bIsExit Then Exit Sub End If
Dim sngStartTime As Single '该变量用来记录开始时间 sngStartTime = GetTickCount '开始时间为计算机的开机时间 Do Until (GetTickCount - sngStartTime) > delayMilliseconds DoEvents '转让控制权 Loop End SubPrivate Sub Command1_Click() '开始按钮 Timer1.Enabled = True Text1.Text = "开始时间:" & Now End Sub Private Sub Start() If bIsExit Then Exit Sub End If
TimeDelay (TimeLen) '延时
Text1.Text = Text1.Text & vbNewLine & "输出时间:" & Now Text1.SelStart = Len(Text1.Text) End SubPrivate Sub Command2_Click() '结束按钮 Timer2.Enabled = False bIsExit = True Unload Me End SubPrivate Sub Form_Load() bIsExit = False TimeLen = 5000 '设置输出时间间隔 End SubPrivate Sub Timer1_Timer() '定时器参数设置为 1秒 Call Start End SubPrivate Sub ShowTime() lblTime.Caption = Now End SubPrivate Sub Timer2_Timer() '定时器参数设置为1秒,显示当前时间 Call ShowTime End Sub
已经关闭 timer ,但是还是无法关闭程序。
问题出在 TimeDelay 过程中;Do Until (GetTickCount - sngStartTime) > delayMilliseconds把上面的《大于号》改成《小于等于》就行了;Do Until (GetTickCount - sngStartTime) <= delayMilliseconds
拜托 内部死循环了吧 不用 doevents 延时 用个timmer控件不行吗
不对吧,8楼兄弟,是你搞反了,untill 条件后就跳出循环了。
do while doevents ... loopdo 。。doevents ,。。loop 本身就是毫无意义的延时只有多线程的计时器事件那个api能保证稍微精准些,其他的延时一概没有意义 为了保持控制权,timer 事件足够了,timer不准确还存在系统级问题,这是不可避免的,也并非全是时间不准确的问题;每个线程只运行20ms;怎么可能让一个timer持续占用时间片考虑新的思路吧
靠!!! csdn也跟百度是的,吞楼了是吗、?
本帖最后由 bcrun 于 2012-05-27 16:52:44 编辑
本帖最后由 bcrun 于 2012-05-27 16:49:47 编辑
本帖最后由 bcrun 于 2012-05-27 16:52:12 编辑
本帖最后由 bcrun 于 2012-06-21 09:59:25 编辑
在你的代码中,禁用 Timer 仅仅是使它下一次不触发 OnTimer 事件,并不能停止当前的循环操作。如下:Dim blnStop As BooleanPublic Sub TimeDelay(delayMilliseconds As Long) '----------------------- '为程序进行延时的子过程 'Do Until 条件.........loop '这个条件是为假才会执行 直到为真停止 '----------------------- On Error Resume Next
'此处加上程序退出判断 If bIsExit Then Exit Sub End If
Dim sngStartTime As Single '该变量用来记录开始时间 sngStartTime = GetTickCount '开始时间为计算机的开机时间 Do Until (GetTickCount - sngStartTime) > delayMilliseconds DoEvents '转让控制权 If blnStop Then Exit Do '检查停止标志 Loop End SubPrivate Sub Command2_Click() '结束按钮 blnStop = True Timer2.Enabled = False bIsExit = True Unload Me End Sub
当然,也可以这样,省掉 blnStop 变量:Public Sub TimeDelay(delayMilliseconds As Long) '----------------------- '为程序进行延时的子过程 'Do Until 条件.........loop '这个条件是为假才会执行 直到为真停止 '----------------------- On Error Resume Next
'此处加上程序退出判断 If bIsExit Then Exit Sub End If
Dim sngStartTime As Single '该变量用来记录开始时间 sngStartTime = GetTickCount '开始时间为计算机的开机时间 Do Until (GetTickCount - sngStartTime) > delayMilliseconds DoEvents '转让控制权 If Not Timer1.Enabled Then Exit Do '***************** 检查停止标志 Loop End SubPrivate Sub Command2_Click() '结束按钮 Timer1.Enabled = False '不明白你原来禁止 Timer2 的用意 bIsExit = True Unload Me End Sub
在ide里面,运行程序,command1后有输出,点了command2之后,程序没有终止,但是这个时候在ide里面暂停程序,会发现程序中止在TimeDelay过程里面.至少在TimeDelay里面循环的过程里面加上对退出状态的检查,以便能及时退出.
Public Sub TimeDelay(delayMilliseconds As Long)没有写2个Timer的时间设置,如果两个Timer处理过程用了1秒,而timer是0.5秒触发一次,也会有问题.timer对象似乎不可重入,而已两个timer会互相影响.
Option Explicit
Dim bexit As Boolean
Private Sub Form_Load()
Debug.Print NUm & " Load me ..."
NUm = NUm + 1
Open "c:\yw.txt" For Output As #1
'没有文件关闭的语句,程序结束后系统会自动写入文件,并且关闭文件
End SubPrivate Sub Timer1_Timer()
'Timer1.Interval=20'变态设置,在20ms循环根本不结束的.
Dim i, j, a, b
a = Timer
For i = 1 To 1200
For j = 1 To 1200
b = j
DoEvents
'If bexit = True Then Exit Sub
Next
Next
Print #1, "Timer1 " & Timer, Timer - a
End SubPrivate Sub Timer2_Timer()
'Timer1.Interval=30'变态设置,在30ms循环根本不结束的.
Dim i, j, a, b
b = Timer
For i = 1 To 1200
For j = 1 To 1200
a = j
DoEvents
'If bexit = True Then Exit Sub
Next
Next
Print #1, "Timer2 " & Timer, Timer - b
End Sub
输出文件Timer2 36721.02 1.609375
Timer2 36722.63 1.578125
Timer2 36724.23 1.578125
Timer2 36725.89 1.625
Timer2 36727.5 1.578125
Timer2 36729.22 1.6875
Timer1 36730.63 11.21875 timer1的运行受到了影响,编译和不编译都是受影响的
Public Declare Function GetTickCount Lib "kernel32" () As Long'以下都在窗体中,窗体包含 2个定时器,2个按钮,1个标签,1个文本矿
Private bIsExit As Boolean
Private bIsWaiting As Boolean, bIsProcess As Boolean
Private TimeLen As Integer
'=======================================================
'程序功能:点击开始 Command2 时,程序每隔5秒输出当前时间
'该程序问题:单击结束按钮 Command2 时无法结束
'=======================================================Public Sub TimeDelay(delayMilliseconds As Long)
'-----------------------
'为程序进行延时的子过程
'Do Until 条件.........loop '这个条件是为假才会执行 直到为真停止
'-----------------------
On Error Resume Next
'此处加上程序退出判断
If bIsExit Then
Exit Sub
End If
Dim sngStartTime As Single '该变量用来记录开始时间
sngStartTime = GetTickCount '开始时间为计算机的开机时间
Do Until (GetTickCount - sngStartTime) > delayMilliseconds
DoEvents '转让控制权
Loop
End SubPrivate Sub Command1_Click()
'开始按钮
Timer1.Enabled = True
Text1.Text = "开始时间:" & Now
End Sub
Private Sub Start() If bIsExit Then
Exit Sub
End If
TimeDelay (TimeLen) '延时
Text1.Text = Text1.Text & vbNewLine & "输出时间:" & Now
Text1.SelStart = Len(Text1.Text)
End SubPrivate Sub Command2_Click()
'结束按钮
Timer2.Enabled = False
bIsExit = True
Unload Me
End SubPrivate Sub Form_Load()
bIsExit = False
TimeLen = 5000 '设置输出时间间隔
End SubPrivate Sub Timer1_Timer()
'定时器参数设置为 1秒
Call Start
End SubPrivate Sub ShowTime()
lblTime.Caption = Now
End SubPrivate Sub Timer2_Timer()
'定时器参数设置为1秒,显示当前时间
Call ShowTime
End Sub
已经关闭 timer ,但是还是无法关闭程序。
...
loopdo 。。doevents ,。。loop 本身就是毫无意义的延时只有多线程的计时器事件那个api能保证稍微精准些,其他的延时一概没有意义
为了保持控制权,timer 事件足够了,timer不准确还存在系统级问题,这是不可避免的,也并非全是时间不准确的问题;每个线程只运行20ms;怎么可能让一个timer持续占用时间片考虑新的思路吧
'-----------------------
'为程序进行延时的子过程
'Do Until 条件.........loop '这个条件是为假才会执行 直到为真停止
'-----------------------
On Error Resume Next
'此处加上程序退出判断
If bIsExit Then
Exit Sub
End If
Dim sngStartTime As Single '该变量用来记录开始时间
sngStartTime = GetTickCount '开始时间为计算机的开机时间
Do Until (GetTickCount - sngStartTime) > delayMilliseconds
DoEvents '转让控制权
If blnStop Then Exit Do '检查停止标志
Loop
End SubPrivate Sub Command2_Click()
'结束按钮
blnStop = True
Timer2.Enabled = False
bIsExit = True
Unload Me
End Sub
'-----------------------
'为程序进行延时的子过程
'Do Until 条件.........loop '这个条件是为假才会执行 直到为真停止
'-----------------------
On Error Resume Next
'此处加上程序退出判断
If bIsExit Then
Exit Sub
End If
Dim sngStartTime As Single '该变量用来记录开始时间
sngStartTime = GetTickCount '开始时间为计算机的开机时间
Do Until (GetTickCount - sngStartTime) > delayMilliseconds
DoEvents '转让控制权
If Not Timer1.Enabled Then Exit Do '***************** 检查停止标志
Loop
End SubPrivate Sub Command2_Click()
'结束按钮
Timer1.Enabled = False '不明白你原来禁止 Timer2 的用意
bIsExit = True
Unload Me
End Sub