最近做一个小程序,用的是winsock。接收到某仪器的命令后,给它发送文件,在发送的过程中每发送20条记录后需要该仪器响应一下,然后才接着发送。
在函数sendFile(),使用了一个全局变量sentCount来记录已发送多少字节,以便于下次接着发送。
但是在测试时发现,有时候会重复发送某一段记录。
想来想去,感觉很像是以前看java时的synchronize所讲的“函数同步”的问题。于是在调用sendFile前,把sentCount输出一看,果然有重复的。
于是希望实现类似于java中的synchronize的方法。在网上找了下,大约涉及到以下几个api函数:
waitForsingleObject //但网上的示例大多是shell调用一个外部程序,而不是自己内部的函数,不知道hProcess参数怎么写
EnterCriticalSection/LeaveCriticalSection  //没找到完整的例子,试着写了下,老是崩溃,内存不能为write再仔细看sendFile函数内部可能导致同步的地方,分析可能是在其中调用winsock.SendData造成的,
原代码如下:
    m_Sender.SendData bytToSend()
    DoEvents
    sentCount = sentCount + (iEnd - iStart) 由于 sentCount的更改在sendData之后,得不及时的更新(个人这么认为的)
于是改成下面的:
    sentCount = sentCount + (iEnd - iStart)
    m_Sender.SendData bytToSend()
    DoEvents
测试时确实没有发现重复发送的问题了,但感觉还不保险。并没有真正地做到“同步”。
请问有没有人遇到过类似的问题,怎么解决的?尤其是上面提到的几个api函数,在这种情况下怎么用 ?感激不尽。

解决方案 »

  1.   

    sentCount = sentCount + (iEnd - iStart)
      m_Sender.SendData bytToSend()
      DoEvents
    这样就行了,m_Sender.SendData bytToSend()
      sentCount = sentCount + (iEnd - iStart) 
      DoEvents
    这样应该也可以,但是还是上边的保险
      

  2.   

    dim flag as integer'0-无任务,>0任务号,比如a的任务号1,b的任务号2
    sub a()
     do
      doevents
      if flag=0 then
       flag=1
       if flag=1 then exit do
      endif
     loop
     '...
     flag=0
    end sub
    sub b()
     do
      doevents
      if flag=0 then
       flag=2
       if flag=2 then exit do
      endif
     loop
     '...
     flag=0
    end sub
      

  3.   

    在不调用外部控件的情况,只是纯vb代码,确实是同步的。
    但是,如果用到了winsock、mscomm等控件时,好像就不一定了。
      

  4.   

    把二楼那段破代码改为if flag=0 then exit sub
    你反正这次不发下次可以发的if flag >0 then exit sub
    flag =1
     sentCount = sentCount + (iEnd - iStart)
      m_Sender.SendData bytToSend()
      DoEvents
    flag =0
      

  5.   

    vb一般不使用,会挂掉的Public Type CRITICAL_SECTION
        dummy As Long
    End Type
    Public sect As CRITICAL_SECTION
    Public Declare Sub EnterCriticalSection Lib "kernel32" (lpCriticalSection As CRITICAL_SECTION)  '进入临界区
    Public Declare Sub LeaveCriticalSection Lib "kernel32" (lpCriticalSection As CRITICAL_SECTION)  '离开临界区Call EnterCriticalSection(sect)
    Call LeaveCriticalSection(sect)
      

  6.   

    说我的代码破?
    你看看EnterCriticalSection对应的汇编代码吧。
      

  7.   

    我又检查了所有代码,把一些关键的状态、计数等全局变量的改变放到了winsock.SendData之前,从表象上看是正常了。
    看来以后在使用外部控件的某些可能有延时的方法时,要小心了。权当经验教训吧。
    小小遗憾,还是没能在vb6中实现一个自定义函数类似于synchronize的方法,虽然一般都是用在多线程的同步上。
      

  8.   

    同步问题加信标
    Private m_IsSending As Boolean  If m_IsSending Then Exit Sub '等下次空闲时再发'
      ...
      m_IsSending = True
      m_Sender.SendData bytToSend()
      DoEvents
      sentCount = sentCount + (iEnd - iStart)  
      m_IsSending = False
      

  9.   

    我2#楼的代码就是在vb6中实现一个自定义函数类似于synchronize的方法。
    用在Timer控件数组模拟多线程的工程代码中已经十多年了。
      

  10.   

    赵忠,在这里是否会响应其他Timer的事件?  endif
     loop
     '...     '这里正在执行是否有办法中断?
     flag=0
    end sub
      

  11.   


    没办法中断上边的loop等待是多余的,有中断的话更错
      

  12.   

    在'...里面的DoEvents可以被其它Timer中断啊。