Doevents 和 timer 冲突问题
--------------------编程问答-------------------- 没细看你的代码,好像不全。。。猜测是这样的:
可能在你关闭的时候有 TIMER 还在执行;
像你这样的情况( TIMER中有 DOEVENTS ),最好是等这类 TIMER 结束任务后,
禁用掉(TIMER1.Enabled = False),然后再关闭进程;
--------------------编程问答-------------------- 如果咋调用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 Sub
Private 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 Sub
Private 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的运行受到了影响,编译和不编译都是受影响的 --------------------编程问答-------------------- 还是在循环,长时间的操作里面判断退出标志,有退出标志了就不循环了.
退出前关闭所有timer. --------------------编程问答-------------------- 这个显然和DoEvents没有关系,是你没有用好的原因。建议你仔细检查,在退出陷入死循环时,点击:Ctrl+Break,终止运行,看看程序步停在什么地方,再单步执行,一般都能发现问题所在。 --------------------编程问答--------------------
你分析的很对,但是如何加入退出状态检查呢,如何完善这个程序呢,这个问题困扰了我2年了,我做了一个服务器程序,类似上面的程序架构,就是无法退出。 --------------------编程问答-------------------- 各位老师,我重新发我写的程序,完整的,请大家调试
--------------------编程问答--------------------
'此语句放在一个独立的 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 Sub
Private 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 Sub
Private Sub Command2_Click()
'结束按钮
Timer2.Enabled = False
bIsExit = True
Unload Me
End Sub
Private Sub Form_Load()
bIsExit = False
TimeLen = 5000 '设置输出时间间隔
End Sub
Private Sub Timer1_Timer()
'定时器参数设置为 1秒
Call Start
End Sub
Private Sub ShowTime()
lblTime.Caption = Now
End Sub
Private 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
...
loop
do 。。doevents ,。。loop 本身就是毫无意义的延时
只有多线程的计时器事件那个api能保证稍微精准些,其他的延时一概没有意义
为了保持控制权,timer 事件足够了,timer不准确还存在系统级问题,这是不可避免的,也并非全是时间不准确的问题;每个线程只运行20ms;怎么可能让一个timer持续占用时间片
考虑新的思路吧 --------------------编程问答-------------------- 靠!!! csdn也跟百度是的,吞楼了是吗、? --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 这个问题比较难解决,我采取用的是延迟退出,延迟时间足够长,暂且解决。 --------------------编程问答-------------------- --------------------编程问答-------------------- 在你的代码中,禁用 Timer 仅仅是使它下一次不触发 OnTimer 事件,并不能停止当前的循环操作。
如下:
Dim blnStop As Boolean
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 blnStop Then Exit Do '检查停止标志
Loop
End Sub
Private 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 Sub
Private Sub Command2_Click()
'结束按钮
Timer1.Enabled = False '不明白你原来禁止 Timer2 的用意
bIsExit = True
Unload Me
End Sub
--------------------编程问答-------------------- 没冲突,纯属用法不当! --------------------编程问答--------------------
补充:VB , 基础类