搞了好久都搞不定Winsock的问题,请大神帮忙:使用Winsock控件接收刷卡数据,每秒记录数大概在5到8条,然后存入到SQL SERVER数据表中,为防止界面卡死,中间使用doevents,但是运行一段时间后在doevents这一行出现“错误号:28 错误描述:Out of stack space 错误源:Rfid 错误行号:2061”错误,实在搞不懂doevents还会出这个错?部分代码:Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
On Error GoTo lblErr:.....2060                Me.Text5.Text = strCardNo '卡号2061                DoEvents2062                Me.txtAll.Text = strls...lblExit:
    Exit Sub
lblErr:
    
    
    If Err.Number = 28 Then 'Out of stack space 可能过程的循环调用是造成的堆栈溢出
905    Open App.Path & "\log.txt" For Append As FreeNum
906    Print #FreeNum, "发生错误时间:" & Now() & " 错误号:" & Err.Number & " 错误描述:" & Err.Description & " 错误源:" & Err.Source & " 错误行号:" & Erl
907    Close FreeNum
910        If cn.State = 1 Then cn.Close
911        cn.Open strconn
        Exit Sub
    End If

解决方案 »

  1.   

    DataArrival 是“有数据送达”的时候才触发。
    这个时候应该取走缓冲区中的数据,并做相关的处理。在这个事件过程中,用不着 DoEvents 吧!
      

  2.   

    不用DoEvents ,这个界面运行半个小时就无响应了,我这个是要求一年中除了春节那几天假期之外,其它时间是24小时无休的
      

  3.   

    用一个FIFO缓冲区……
      

  4.   

    Winsock1_DataArrival 的完整代码或者这个doevents前后各20行代码发出来看看。
    估计是有一个循环在这里吧。基本上你这玩意就是循环搞死的。猜你是在dataarrival以后循环等待后续数据了。不加doevents就在里面傻等。加了doevents数据一来就形成嵌套调用堆栈两下半就爆了
      

  5.   

    仅供参考:Private Sub tcpRTB_DataArrival(ByVal bytesTotal As Long)
    Dim i As Long
    Dim p As Long
    Dim qn As Long
    Dim s As Long
    Dim e As Long
    Dim Total_Length As Long
    Dim iBuf() As Byte
    Dim lnx As String
    Const STX = 2
    Const ETX = 3
    Dim L As Long
    Dim XORSUM As Long
    Dim BYTESUM As Long
    Dim strMsgToProcess As String
    Dim bt As Long
        On Error Resume Next
        If INtcpRTB_DataArrival Then
            INtcpRTB_DataArrival_TotalBytes = bytesTotal
            if bytesTotal<128 Then
                LogDebug "ReEnter tcpRTB_DataArrival bytesTotal=" + CStr(bytesTotal)
                Exit Sub
            Else
                LogErrMsg "ReEnter tcpRTB_DataArrival bytesTotal=" + CStr(bytesTotal) + ">=128"
            End If
        End If
        bt = bytesTotal
        INtcpRTB_DataArrival = True
    REDATA:
    '   收当前流
        ReDim iBuf(bt - 1)
        tcpRTB.GetData iBuf
    '   log每个收到的字节
        i = 0
        lnx = "RTB-->BYTE:" + Right("0000000" + Hex(i), 8) + "-"
        For i = 0 To bt - 1
            lnx = lnx + " " + Right("0" + Hex(iBuf(i)), 2)
            If i Mod 16 = 15 Then
                LogRX lnx
                lnx = "RTB-->BYTE:" + Right("0000000" + Hex(i + 1), 8) + "-"
            End If
        Next
        i = bt - 1
        If i Mod 16 <> 15 Then
            LogRX lnx
        End If'   将本次收到字节放到接收缓冲区末尾
        For i = 0 To bt - 1
            iRTB(iRTBn + i) = iBuf(i)
        Next
        iRTBn = iRTBn + bt
    '   从接收缓冲区中逐个解包
        qn = iRTBn '剩余要解包字节数
        p = 0 '本次解包的首字节
        Do
            '0   1    2   3  4   5   6  |7   ...
            'STX-DATA-ETX-XORSUM-BYTESUM|STX-DATA-ETX-XORSUM-BYTESUM|...
            If qn >= 7 Then
                For i = 0 To qn - 1
                     If STX = iRTB(p + i) Then Exit For
                Next
                If i >= qn Then
                    For i = 0 To qn - 1
                        iRTB(i) = iRTB(p + i)
                    Next
                    iRTBn = qn
                    Exit Do '找不到STX
                End If
                s = i
                For i = s To qn - 1
                     If ETX = iRTB(p + i) Then Exit For
                Next
                If i >= qn Then
                    For i = 0 To qn - 1
                        iRTB(i) = iRTB(p + i)
                    Next
                    iRTBn = qn
                    Exit Do '找不到ETX
                End If
                e = i
                If e - p + 4 >= qn Then
                    For i = 0 To qn - 1
                        iRTB(i) = iRTB(p + i)
                    Next
                    iRTBn = qn
                    Exit Do 'ETX之后不足4个字节
                Endif
                Total_Length = e - s + 5
                L = e - s - 1
                XORSUM = STX
                BYTESUM = STX
                strMsgToProcess = ""
                For i = 1 To L
                    XORSUM = XORSUM Xor iRTB(p + s + i)
                    BYTESUM = BYTESUM + iRTB(p + s + i)
                    strMsgToProcess = strMsgToProcess + ChrW(iRTB(p + s + i))
                Next
                XORSUM = XORSUM Xor ETX
                BYTESUM = BYTESUM + ETX
                If iRTB(p + e + 1) = Asc(Hex((XORSUM Mod 256) \ 16)) And iRTB(p + e + 2) = Asc(Hex(XORSUM Mod 16)) And iRTB(p + e + 3) = Asc(Hex((BYTESUM Mod 256) \ 16)) And iRTB(p + e + 4) = Asc(Hex(BYTESUM Mod 16)) Then
                    LogRX "rtb-->" + strMsgToProcess
                    RTBput strMsgToProcess
                    TimerRTB.Enabled=True
                Else
                    LogRX "rtb-->CKSUM error!"
                End If
            NEXTMSG:
                p = p + Total_Length
                qn = qn - Total_Length
                If qn <= 0 Then
                    iRTBn = 0
                    Exit Do
                End If
            Else
                If p > 0 Then
                    If qn > 0 Then
                        For i = 0 To qn - 1
                            iRTB(i) = iRTB(p + i)
                        Next
                    End If
                    iRTBn = qn
                End If
                Exit Do
            End If
        Loop
        If INtcpRTB_DataArrival_TotalBytes > 0 Then
            bt = INtcpRTB_DataArrival_TotalBytes
            INtcpRTB_DataArrival_TotalBytes = 0
            LogDebug "REDATA bt=" + CStr(bt)
            GoTo REDATA
        End If
        INtcpRTB_DataArrival = False
    End Sub
      

  6.   

    我学Basic是95年,第一次接触VB是99年
      

  7.   

    我写经典VB6代码的时候,你可能还没出生。我猜。
    参考:www.xajh.com QQ群:106786637
     胡说八道……
      

  8.   

    C:\www\MUD.VBP
    Type=Exe
    Form=MUD.frm
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\WINDOWS\system32\stdole2.tlb#OLE Automation
    Object={C1A8AF28-1257-101B-8FB0-0020AF039CA3}#1.1#0; MCI32.OCX
    Object={248DD890-BB45-11CF-9ABC-0080C7E7B78D}#1.0#0; MSWINSCK.OCX
    Object={82351433-9094-11D1-A24B-00A0C932C7DF}#1.5#0; ANIGIF.OCX
    Form=MFTP.frm
    Object={48E59290-9880-11CF-9754-00AA00C00908}#1.0#0; MSINET.OCX
    Object={EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}#1.1#0; shdocvw.dll
    Form=MWEB.frm
    Form=MMNU.frm
    Module=Module1; mmdl.bas
    IconForm="Form1"
    Startup="Form1"
    HelpFile=""
    Title="WWW"
    ExeName32="WWW.exe"
    Command32=""
    Name="MUD"
    HelpContextID="0"
    CompatibleMode="0"
    MajorVer=6
    MinorVer=7
    RevisionVer=2
    AutoIncrementVer=0
    ServerSupportFiles=0
    VersionCompanyName="乐斗士"
    VersionFileDescription="互联网游戏"
    VersionProductName="《笑傲江湖-精忠报国》"
    CompilationType=-1
    OptimizationType=2
    FavorPentiumPro(tm)=0
    CodeViewDebugInfo=0
    NoAliasing=0
    BoundsCheck=0
    OverflowCheck=0
    FlPointCheck=0
    FDIVCheck=0
    UnroundedFP=0
    StartMode=0
    Unattended=0
    Retained=0
    ThreadPerObject=0
    MaxNumberOfThreads=1[MS Transaction Server]
    AutoRefresh=1     行数|文件名
            3|C:\www\MMDL.BAS
           58|C:\www\MWEB.frm
          940|C:\www\MMNU.FRM
          364|C:\www\MFTP.FRM
         6326|C:\www\MUD.frm
    1999年
      

  9.   

    https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0&xthttps=111111&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E7%AC%91%E5%82%B2%E6%B1%9F%E6%B9%96%E7%B2%BE%E5%BF%A0%E6%8A%A5%E5%9B%BD
      

  10.   

    因为DoEvents是启动另一个消息循环。你每接到个数据就启动一个消息循环,out of stack是必然的。正确的办法是把socket放到工作线程里面去。
      

  11.   

    楼上的是把VB6当成C++来玩啊。
      

  12.   

    事件大量触发,导致递归太深,不然你给doevents前面加上on error resume next吧
      

  13.   

    你会用EditBin.exe修改VB6生成的EXE文件的默认堆栈大小吗?
      

  14.   

    有无限递归的bug的时候跑来跟我说改堆栈大小……不懂别装懂。
      

  15.   

    为什么doevents会导致调用堆栈溢出,本质是因为doevents的实现的伪代码是
    while(GetMessage(&Msg,NULL,0,0))
    {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
    }

    DispatchMessage(&Msg);
    内部调用了WndProc()
    而WndProc调用了你触发事件的处理函数(比如button1_click或者datarecived)
    可以想象,当datarecived大量触发,并且前者没有执行完,你调用了doevents,它调用了新的datarecived
    如果很多这样的,堆栈自然就爆了。蒋老大说的是对的,我只是展开来说一下。
      

  16.   


    没有VB,拿VB.net写一个故意溢出的定时器事件,感受下