搜索
bottom↓
回复: 16

针对这个用doevents 在VB怎么解决啊

[复制链接]

出0入0汤圆

发表于 2009-6-28 17:18:09 | 显示全部楼层 |阅读模式
Private Sub Command20_Click()  
    Dim Temp As String  
    Dim buff_out7() As Byte  
    ReDim buff_out7(8)  
    Dim u As Long  
    MSComm1.Settings = "9600,N,8,1"   ' 9600 波特,无奇偶校验,8 位数据,一个停止位。  
    MSComm1.InputLen = 0              ' 当输入占用时,告诉控件读入整个缓冲区。  
    buff_out7(0) = &HAA  
    buff_out7(1) = &HAA  
    buff_out7(2) = &HFF  
    buff_out7(3) = &H1  
    Open App.Path & "\2.txt" For Input As #2  
        Line Input #2, Temp  
    Close #2  
    u = Val(Temp)  
    If u > 0 And u < 65536 Then  
    buff_out7(5) = u Mod 256  
    buff_out7(4) = u \ 256  
    buff_out7(6) = &H0  
    buff_out7(7) = &H0  
    buff_out7(8) = &HFF  
        If MSComm1.PortOpen = False Then  
          Label1.Caption = "您的串口现在是关闭状态,请先打开串口"  
        Else  
            MSComm1.Output = buff_out7  
            Label1.Caption = ""  
        End If  
    End If  
End Sub  



针对这个用doevents 怎么解决啊 ?有的说用doevents 可以解决我VB无规律死机的问题 。就是不知道什么时候鼠标就不能操作了,没有一点规律可循。只能关闭VB的exe文件,再次打开,就回出现串口占用,唯一的办法就是重启电脑。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2009-6-28 18:55:15 | 显示全部楼层
这个里面没有要用到doevents的地方

出0入0汤圆

发表于 2009-6-28 21:13:45 | 显示全部楼层
在任务管理器中,关闭占用串口的程序试试。

再不然就用回调函数,不要让程序总在那儿等待。

出0入0汤圆

发表于 2009-6-28 21:51:52 | 显示全部楼层
用到循环的地方,建议都加上doevents 使CPU不至于死等

出0入0汤圆

 楼主| 发表于 2009-6-28 22:29:43 | 显示全部楼层
回2楼 在任务管理器中中根本就删除不了 唯一的办法就是重启电脑 否则就提示串口占用 你说回调函数怎么个回调法 谢谢!
回【3楼】 general_dwf,但是我VB里面发送命令的地方都没有用到循环啊。就如上面的命令。感谢!

出0入0汤圆

发表于 2009-6-28 23:28:10 | 显示全部楼层
taskkill /f /t /pid xxx
xxx就是你进程的pid
必然能关上...
除非有双进程互锁...

出0入0汤圆

 楼主| 发表于 2009-6-29 10:18:36 | 显示全部楼层
不懂ls的“taskkill /f /t /pid xxx ”什么意思,能否具体说下

出0入0汤圆

发表于 2009-6-29 19:15:22 | 显示全部楼层
LZ发了这么多贴, 我的理解从你这块代码似乎看不到死机的原因, 你整个VB工程代码仔细检查过没有?

例如有没有用到定时器之类的?  不定时假死有可能是别的地方引起的.

如果愿意, 可以把整个代码给我, 我帮你看看.

出0入0汤圆

 楼主| 发表于 2009-6-29 20:43:10 | 显示全部楼层
我也仔细检查过 单纯的往助手上发协议是很顺畅的 就是和下位机连接上后就有时候VB界面不好使了
用到了定时器,如下:
'定时器延时
Private Sub Timer1_Timer()
   Dim longth As Integer
    If Check1.Value = 1 Then
    intOutMode = 1
    Else
    intOutMode = 0
    End If
    strSendText = pl.Text + zkb.Text + sq.Text
    If intOutMode = 0 Then
        MSComm1.Output = strSendText
    Else
        longth = strHexToByteArray(strSendText, bytSendByte())
        If longth > 0 Then
            MSComm1.Output = bytSendByte
      End If
    End If
    If Label16.Caption <> CStr(Time) Then
        Label16.Caption = Time$
    End If
End Sub

出0入0汤圆

发表于 2009-6-29 21:08:24 | 显示全部楼层
你的定时器多长时间触发一次?

这段代码本身没看到循环, 用到一个自己写的函数:strHexToByteArray, 该函数代码没看到.   按理应该不会引起界面假死.  除非你的定时器的时间定得太短, 在上一次的事件处理没结束的情况下再次触发,  如果是这种情况, 你可以尝试在定时器代码的前面加上: Timer1.Enabled=False, 进入代码就关闭定时器, 在代码最后加上Timer1.Enabled=true,  看看情况有没有改善.

出0入0汤圆

 楼主| 发表于 2009-6-30 10:32:30 | 显示全部楼层
我看了下 就是下面用了循环:

Function strHexToByteArray(strText As String, bytByte() As Byte) As Integer
   
    Dim HexData As Integer          '十六进制(二进制)数据字节对应值
    Dim hstr As String * 1          '高位字符
    Dim lstr As String * 1          '低位字符
    Dim HighHexData As Integer      '高位数值
    Dim LowHexData As Integer       '低位数值
    Dim HexDataLen As Integer       '字节数
    Dim StringLen As Integer        '字符串长度
    Dim Account As Integer          '计数
    Dim n As Integer
    'strText = ""                   '设初值
    HexDataLen = 0
    strHexToByteArray = 0
   
    StringLen = Len(strText)
    Account = StringLen \ 2
    ReDim bytByte(Account)
   
    For n = 1 To StringLen                 'For...Next循环语句
   
        Do                                              '清除空格
            hstr = Mid(strText, n, 1)
            n = n + 1
            If (n - 1) > StringLen Then
                HexDataLen = HexDataLen - 1
               
                Exit For
            End If
        Loop While hstr = " "                   'DO...Loop While循环
        
        Do
            lstr = Mid(strText, n, 1)
            n = n + 1
            If (n - 1) > StringLen Then
                HexDataLen = HexDataLen - 1
               
                Exit For
            End If
        Loop While lstr = " "
        n = n - 1
        If n > StringLen Then
            HexDataLen = HexDataLen - 1
            Exit For
        End If
        
        HighHexData = ConvertHexChr(hstr)
        LowHexData = ConvertHexChr(lstr)
        
        If HighHexData = -1 Or LowHexData = -1 Then     '遇到非法字符中断转化
            HexDataLen = HexDataLen - 1
            
            Exit For
        Else
            
            HexData = HighHexData * 16 + LowHexData
            bytByte(HexDataLen) = HexData
            HexDataLen = HexDataLen + 1
            
            
        End If
                        
    Next n
   
    If HexDataLen > 0 Then                              '修正最后一次循环改变的数值
        HexDataLen = HexDataLen - 1
        ReDim Preserve bytByte(HexDataLen)
    Else
        ReDim Preserve bytByte(0)
    End If
   
    If StringLen = 0 Then                               '如果是空串,则不会进入循环体
        strHexToByteArray = 0
    Else
        strHexToByteArray = HexDataLen + 1
    End If
   
End Function

出0入0汤圆

发表于 2009-6-30 10:44:36 | 显示全部楼层
问题应该出在这个strHexToByteArray函数, 在

For n = 1 To StringLen
后面加上DoEvents

还有后面的DO循环的第一行都加上DoEvents, 应该可以解除界面死锁的问题.


如果想替换掉字符串中的空格,  可以使用replace函数.


另外, 你这个循环需要优化, 外层的FOR循环, 里面的两个DO循环, 都是字符串的长度, 循环的总次数是长度的几次方.如果定时器间隔很短, 会重复进入, 会导致意料不到的事情发生.


还有, 看到ConvertHexChr这个函数, 根据LZ的代码风格, 估计这个函数的代码也会用到循环, 建议LZ对 strHexToByteArray 所涉及到的代码进行优化, 因为strHexToByteArray是定时器要用到的, 本身定时器就是一个大循环, 这种密集运算的循环会占用CPU资源不放, 建议LZ在必要的地方放置DOEvents语句.

出0入0汤圆

 楼主| 发表于 2009-6-30 11:13:28 | 显示全部楼层
恩 好的 你说的除了这样修改还怎么修改(就加了2个DoEvents ):
Function strHexToByteArray(strText As String, bytByte() As Byte) As Integer
   
    Dim HexData As Integer          '十六进制(二进制)数据字节对应值
    Dim hstr As String * 1          '高位字符
    Dim lstr As String * 1          '低位字符
    Dim HighHexData As Integer      '高位数值
    Dim LowHexData As Integer       '低位数值
    Dim HexDataLen As Integer       '字节数
    Dim StringLen As Integer        '字符串长度
    Dim Account As Integer          '计数
    Dim n As Integer
    'strText = ""                   '设初值
    HexDataLen = 0
    strHexToByteArray = 0
   
    StringLen = Len(strText)
    Account = StringLen \ 2
    ReDim bytByte(Account)
   
    For n = 1 To StringLen                 'For...Next循环语句
        DoEvents
        Do                                              '清除空格
            hstr = Mid(strText, n, 1)
            n = n + 1
            If (n - 1) > StringLen Then
                HexDataLen = HexDataLen - 1
               
                Exit For
            End If
        Loop While hstr = " "                   'DO...Loop While循环
        DoEvents
        Do
            lstr = Mid(strText, n, 1)
            n = n + 1
            If (n - 1) > StringLen Then
                HexDataLen = HexDataLen - 1
               
                Exit For
            End If
        Loop While lstr = " "
        n = n - 1
        If n > StringLen Then
            HexDataLen = HexDataLen - 1
            Exit For
        End If
        
        HighHexData = ConvertHexChr(hstr)
        LowHexData = ConvertHexChr(lstr)
        
        If HighHexData = -1 Or LowHexData = -1 Then     '遇到非法字符中断转化
            HexDataLen = HexDataLen - 1
            
            Exit For
        Else
            
            HexData = HighHexData * 16 + LowHexData
            bytByte(HexDataLen) = HexData
            HexDataLen = HexDataLen + 1
            
            
        End If
                        
    Next n
   
    If HexDataLen > 0 Then                              '修正最后一次循环改变的数值
        HexDataLen = HexDataLen - 1
        ReDim Preserve bytByte(HexDataLen)
    Else
        ReDim Preserve bytByte(0)
    End If
   
    If StringLen = 0 Then                               '如果是空串,则不会进入循环体
        strHexToByteArray = 0
    Else
        strHexToByteArray = HexDataLen + 1
    End If
   
End Function

出0入0汤圆

发表于 2009-6-30 11:17:09 | 显示全部楼层
DoEvents要加在DO循环的循环体内, 不是放在外面.

另外, 如果定时器不是需要重复进入的话, 可以每次运算完毕后再触发下一次. 所以在定时器的代码第一行加:
Timer1.Enabled=false
最后一行加:
Timer1.Enabled=True

出0入0汤圆

 楼主| 发表于 2009-6-30 15:39:55 | 显示全部楼层
谢谢gdyaojie ,ConvertHexChr这个函数没有用到循环:

Function ConvertHexChr(str As String) As Integer
   
    Dim test As Integer
   
    test = Asc(str)
    If test >= Asc("0") And test <= Asc("9") Then
        test = test - Asc("0")
    ElseIf test >= Asc("a") And test <= Asc("f") Then
        test = test - Asc("a") + 10
    ElseIf test >= Asc("A") And test <= Asc("F") Then
        test = test - Asc("A") + 10
    Else
        test = -1                                      
    End If
    ConvertHexChr = test
   
End Function

出330入0汤圆

发表于 2009-6-30 15:44:12 | 显示全部楼层
楼主这么多上位机的问题怎么不去CSDN?
在这里问上位机就像在CSDN里问单片机。

出0入0汤圆

 楼主| 发表于 2009-6-30 16:06:33 | 显示全部楼层
去了的 这里的水平高
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 20:01

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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