F8单步调试正常,但是直接运行时接收的数据就不对了。
下面是程序的一段While Not rs.EOF
send1 = CStr("AT+CMGF=1") + Chr(13) + Chr(10)'需要发送的命令字Do
  Comm.Output = send1'发送第一条命令
Loop Until Comm.OutBufferCount = 0 '此处设置一个停顿,用来在一定时间内等待接收ok字符
iTime = CInt(txtWait.Text)
Timer1.Enabled = True          
Call Timer1_Timer            
DoEvents                       (窗体加载时timer的enable是false,此时启动timer,每秒执行一次,倒计时结束后才返回,继续下面的语句。但每次执行完一次后就返回到这里了,不再执行了,而我实际上需要一个循环,doevents加了和没加效果一样,是不是我加的地方不对?)

解决方案 »

  1.   

    看你的意思是要利用timer做一个延时。
    定义个窗体变量 delay
    dim delay as boolean然后改成这样看看
    delay=true
    iTime = CInt(txtWait.Text)
    Timer1.Enabled = True  
    do while delay
        DoEvents   
    loop'timer事件里面设置delay=false
    private sub iTime_timer()
      delay=falseend sub
      

  2.   

    记住延时完了写上iTimer.enable=false,可以也写在timer事件里面
      

  3.   

    我做了个for循环,还是不行
    For i = 1 To 5000
    DoEvents
    Next i
      

  4.   

    5000太少了
    你的textwait写了多少
      

  5.   

    Option Explicit
    Dim delay As BooleanPrivate Sub Command1_Click()
        Timer1.Interval = 5000
        Timer1.Enabled = True
        delay = True
        Do While delay
            DoEvents
        Loop
        MsgBox "delay ok"
    End SubPrivate Sub Timer1_Timer()
        delay = False
        Timer1.Enabled = False
    End Sub看我这一段  在一个窗体上放一个timer 设置enable=false
    然后点击command1 会在5秒以后msgbox 
      

  6.   

    如是想延时,可以用Sleep API函数:Private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)Sleep 5000  '延时5秒
      

  7.   

    不知道 你要实现什么 没看明白你的代码片断 如果想按照规定时间执行的话用api timmer不准确 经常有问题 如果是延时的话不要用sleep 那个api会使系统不响应任何消息  可以采用死循环+devents如果你能把详细代码给我看 可以给我发短消息 附上帖子的 地址 我会回的
      

  8.   

    LZ用faysky2() 的方法应该可以更方便的实现延时。
    不过,要是一定要用延时函数的话到可以:
    Private Sub Relate()       '延时函数
        ct = Timer
    While Timer - ct < 0.05(自己定义要延长的时间 单位/秒)
        DoEvents
    Wend
      

  9.   

    http://www.mcuchina.com/Article/Interface/COM/COMPRG/200411/73.html
      

  10.   

    Private Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount" () As Long'延时 lngmSec 毫秒
    Private Sub Delay(ByVal lngmSec As Long)
    Dim lngStartmSec As Long
    lngStartmSec = GetTickCount
    Do While GetTickCount - lngStartmSec <= lngmSec
    DoEvents
    Loop
    End Sub
      

  11.   

    我的需求是这样的,单击某个按钮后,系统开始从串口向外发送命令,一共有4条命令。
    第一条命令发出后开始等待接收命令,比如3秒钟,时间到了还没有收到返回的命令就放弃,开始向下一个目标发送命令,如果收到返回的命令无论等待时间是否到都继续发送第二条命令。
    我用单步执行的时候,如果收到了返回命令那么程序可以正常执行,但是如果没收到返回命令,程序只是执行了一次Timer事件就返回了,并没有象我所设计的那样循环。
    我现在试了几种延时的方式,效果都不是很好,想请教一下有没有比较可靠,速度也比较快的方式。
    部分代码如下:'先从数据库中提取flags=1也就是需要呼叫的手机号
    sql = "select tel from ip where flags=1"
    Set rs = gcn.Execute(sql)
    While Not rs.EOF'需要发送的命令字
    send1 = CStr("AT+CMGF=1") + Chr(13) + Chr(10)
    send2 = CStr("AT+CMGS=") + "" & Trim(rs!tel) & "" + Chr(13) + Chr(10)
    send3 = CStr("ADRES") + Chr(&H11) + Chr(&H7A)
    send4 = CStr("IP") + "" & txtIP.Text & ""'发送第一条命令
    Comm.Output = send1'此处设置一个停顿,用来在一定时间内等待接收ok字符'这是第一种方法,设置delayTime标志,收到返回命令或者倒计时结束了就将其设为false,但是他的反应速度好象比较慢,本机测试,链路通的情况下,40条命令(每条命令都不长)需要35秒时间,而且最重要的,在数据发送过程中,我没法停止,即便我把程序关掉了,他仍然在运行,必须等他运行完了,我单击VB中的结束按键他才停,虽然我已经在UnLoad事件中写了Timer1.enabled=falsedelayTime = True
    iTime = CInt(txtWait.Text) '设置的等待回应时间
    Timer1.Enabled = True
    Call Timer1_Timer
    Do While delayTime
    DoEvents
    Loop'第二种方法,不能使用,程序就象死机一样
    'Sleep (1000)'第三种方法
    'Delay (1500)'Delay的定义(写在这里以便阅读)
    'Private Sub Delay(ByVal lngmSec As Long)
    'Dim lngStartmSec As Long
    'lngStartmSec = GetTickCount
    'Do While GetTickCount - lngStartmSec <= lngmSec
    'DoEvents
    'Loop
    'End Sub
    '此处用来判断返回是因为接收到了ok字符还是等待时间到了
    '如果接收到了ok字符,那么向该手机发送下一条命令,否则数据库指针
    '下移一条,向下一个手机发送第一条命令If flags = 0 Then '超时未收到OK字符
    List1.AddItem "未收到手机" & Trim(rs!tel) & " 的返回信息,现在向下一个手 机发送命令"
    GoTo NextI '数据库指针下移一个Else '收到OK字符
    flags = 0 '将flags 清0以免与第二次OK回应混淆
    List1.AddItem "手机" & Trim(rs!tel) & " 第一次返回OK"
    End IfComm.Output = send2 '发送第二条命令'等待处理同第一条命令'将该手机连接成功标志位置为1
    sql = "update ip set flags=0 where tel='" & sDel & "'"
    sqlSuccess = "update ip set connectTel=1 where tel= '" & Trim(rs!tel) & "' "
    Set rsSuccess = gcn.Execute(sqlSuccess)NextI:
    rs.MoveNext
    Wend
    rs.Close
    Set rs = Nothing
    Set rsSuccess = Nothing'timer事件
    Private Sub Timer1_Timer()
    Dim Buffer As Variant
    iTime = iTime - 1
    Do While Comm.InBufferCount <> 0 '从缓冲区中读数据
    DoEvents
    Buffer = Comm.Input
    If Buffer = "ok" Then
    flags = 1
    delayTime = False
    Timer1.Enabled = False
    Exit Sub
    End If
    Loop
    If iTime = 0 Then
    flags = 0
    delayTime = False
    Timer1.Enabled = False
    Exit Sub
    End If
    End Sub
      

  12.   

    又是DoEvents惹的祸,先看看MSDN中关于DoEvent的一些说明吧。在使用全局数据时避免 DoEvents
    当一个函数已通过 DoEvents 放弃控制时,可相当安全地再次调用函数。例如,下一过程将检测质数并用 DoEvents 语句周期地启动其它应用程序处理事件:Function PrimeStatus (TestVal As Long) As Integer
       Dim Lim As Integer
       PrimeStatus = True
       Lim = Sqr(TestVal)
       For I = 2 To Lim
          If TestVal Mod I = 0 Then
             PrimeStatus = False
             Exit For
          End If
          If I Mod 200 = 0 Then DoEvents
       Next I
    End Function该代码中每重复 200 次就调用一次 DoEvents 语句。这样一来,当该环境的其余部分对事件作出响应时,只要有必要,PrimeStatus 过程就可继续计算。考虑在调用 DoEvents 期间发生的事情。在其它窗体和应用程序处理事件时将暂停执行应用程序代码。这些事件之一有可能是一个按钮单击操作,它将再次启动 PrimeStatus 过程。这将导致重新进入 PrimeStatus 过程的,但是,因为在函数每次出现时,堆栈都为其参数和局部变量分配了空间,所以重入不会引发冲突。当然,如果过多调用 PrimeStatus,则可能出现“溢出堆栈空间”错误。如果 PrimeStatus 使用或改变模块级变量或全局数据,情况就会完全不同。此时,在 DoEvents 能够返回之前执行 PrimeStatus 的另一个实例,这将导致模块数据或全局数据的值完全不同于它们在调用 DoEvents 之前的值。于是,PrimeStatus 的结果将会难以预料。你的Timer事件函数就会出现函数没有被返回而出现多次调用的情况。'部分代码修改如下:
    发送第一条命令
    Comm.Output = send1
    lngTime=CLng(txtWait.Text)
    Dim lngStartmSec As Long
    Dim Buffer as Variant
    lngStartmSec = GetTickCount
    Do While GetTickCount - lngStartmSec <= lngTime
     If Comm.InBufferCount<>0 Then
       Buffer=Comm.Input
       If Buffer="ok" Then
         '加入处理程序
       Else
         '加入处理程序
       End If
       Exit Do
     End If
     DoEvents  '重点说明:如果VB能方便实现安全的多线程,那么在后台线程实现整个发送代码很方便且不影响界面线程。正是由于VB的缺陷,使得你在界面响应和后台处理上难以平衡,从而导致你的代码出现问题。还是建议在VB中尽量避免使用DoEvents语句,因为你把控制权交给系统后对应用程序就失控了,所以结果就很难预料。
    Loop
    '将该手机连接成功标志位置为1
    Comm.Output = send2 '发送第二条命令
      

  13.   

    API的SLEEP函数,用了确实和死机没什么两样,那么我们可以写一个代替嘛,下面一个是我常用的SLEEP自定义函数。Public Sub SleepIt(SleepTime As Double)  'Sleep
      Dim tmpTime As Double  tmpTime = Timer
      If tmpTime + SleepTime >= 86400 Then
        tmpTime = tmpTime - 86400
      End If
      Do While (Timer - tmpTime) < SleepTime
        DoEvents
      Loop
      
    End Sub
      

  14.   

    还需要说明的一点就是Timer控件是一个线程安全的控件,也就是说如果Timer控件的一个Timer事件没有结束的话,那么它的下一个事件是不会被触发的(看看VB自带的XTimer的例子你就知道)。但是在Timer中加入DoEvents语句,情况又将发生变化,只是这种变化你的应用程序是无法预留。总之,要谨慎使用DoEvents,VB中要想在界面响应和后台处理处理获得一个好的平衡比较难,还是要尽量避免是长时间和多嵌套循环。