最近做一个小程序,用的是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函数,在这种情况下怎么用 ?感激不尽。
在函数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函数,在这种情况下怎么用 ?感激不尽。
解决方案 »
- 如何让mshflexgrid单元格中的字竖着显示?
- 我通过串口发送一个字符串,大约20多个字符,接收端需要延时处理吗?
- 如何用Shell("rasdial vvv")调用VPN
- TREEVIEW控件,如何识别TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)事件
- 怎样抓屏幕上一点或一个指定坐标的矩形的图到一个数组
- 关于注册表的问题,高手、菜鸟都进来看看,呵呵呵
- 我需要一个实用的数据字典管理工具, 帮推荐一下
- 如何在listview控件中的任意一列中添加复选框(checkbox)
- 我想用VB做一个类,此类有8个属性,我想在此类中添加如RECORESET类似的AddNew和UPDATE的方法,该如何写这个类呀!最好有源码,一定加分!
- 我的ADO控件出问题了???回Mr liyang,Miss amstar,Mr tyro
- vb Toolbar 宽度问题
- VB小程序求助
m_Sender.SendData bytToSend()
DoEvents
这样就行了,m_Sender.SendData bytToSend()
sentCount = sentCount + (iEnd - iStart)
DoEvents
这样应该也可以,但是还是上边的保险
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
但是,如果用到了winsock、mscomm等控件时,好像就不一定了。
你反正这次不发下次可以发的if flag >0 then exit sub
flag =1
sentCount = sentCount + (iEnd - iStart)
m_Sender.SendData bytToSend()
DoEvents
flag =0
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)
你看看EnterCriticalSection对应的汇编代码吧。
看来以后在使用外部控件的某些可能有延时的方法时,要小心了。权当经验教训吧。
小小遗憾,还是没能在vb6中实现一个自定义函数类似于synchronize的方法,虽然一般都是用在多线程的同步上。
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
用在Timer控件数组模拟多线程的工程代码中已经十多年了。
loop
'... '这里正在执行是否有办法中断?
flag=0
end sub
没办法中断上边的loop等待是多余的,有中断的话更错