当前位置:编程学习 > VB >>

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 楼  的回复:
如果咋调用TimeDelay延时5秒的过程中按了command2,就产生什么情况?窗体卸载,但是窗体过程还在运行,矛盾了:
在ide里面,运行程序,command1后有输出,点了command2之后,程序没有终止,但是这个时候在ide里面暂停程序,会发现程序中止在TimeDelay过程里面.

至少在TimeDelay里面循环的过程里面加上对退出状态的检查,以便能及时退出.
Public ……


你分析的很对,但是如何加入退出状态检查呢,如何完善这个程序呢,这个问题困扰了我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


--------------------编程问答--------------------
引用 3 楼  的回复:
还是在循环,长时间的操作里面判断退出标志,有退出标志了就不循环了.

退出前关闭所有timer.


已经关闭 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 ,  基础类
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,