找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
楼主: 木头

【求助】创建多线程的问题

  [复制链接]

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2009-11-10 16:54:52 | 显示全部楼层
<p>控件内部的处理肯定是多线程,这个没有问题的.</p>
<p>&nbsp;</p>
<p>因为内部有一个循环用于处理收发队列,如果不使用多线程的话直接会挂起调用线程.</p>
<p>&nbsp;</p>
<p>而为什么有上面的问题,关键在于-----------------你处理数据是同一个线程里!</p>
<p>&nbsp;</p>
<p>也就是说,前台总机可以同时应答20个来电,但是实际能处理这些来电的,如果只有一个部门(比如都是技术问题,而只有一个技术部门),那实际还是串行处理的.</p>
<p>&nbsp;</p>
<p>至于跨线程传递requestID失败,有可能这个ID是一个局部指针类的东西,到了另一线程后这个指针失效了......</p>
<p>&nbsp;</p>
<p>如果真是这样,这可是一个相当麻烦的问题啊....</p>
我就是嗷嗷叫的老马了......

3

主题

50

回帖

0

精华

银牌会员

积分
444
发表于 2009-11-10 23:15:42 | 显示全部楼层
<p>仔细想了一下,老马说的有道理。。。那么按照我目前的理解是,调用Sock的方法,如 .send 或 .accept 后,Winsock 即进入内部的多线程处理去了,而 _DataArrival 这个事件 实际上是运行于 Sock 外部的VB单线程环境的,这样理解应该差不多能解释这个问题了。</p>
<p>今天无奈中下载安装了 <font face="Verdana">PowerTCP_Winsock_ActiveX_Trial.exe</font> ,用他的 <font face="Verdana">Daemon</font> 做侦听放在主窗口,再用它的 <font face="Verdana">Tcp</font> 放在线程窗口,传递它的 <font face="Verdana">Daemon</font><font face="Verdana">.Accept</font> 变量去子线程的 <font face="Verdana">Tcp</font> 中接受应答,这回倒是可以正常运行了,没有再出现 Winsock 的那种奇怪现象。</p>
<p>于是搬了一部分我那个服务程序的代码过来,做了线程内数据库的连接,运行基本正常。只是线程不能开的太多。。。。。我猜测,哪些大型的游戏服务器程序应该也不是每个客户端连接分配一个线程吧,那样的话,系统资源再多都不够用啊。我看了一下我的SQL2000服务器的线程,在我服务程序开到500线程响应500客户端连接的时候,由于我每个线程里面是单独的开了数据库连接的,SQL2000也只开到269个线程来接受我的响应就封顶了啊。因此按照我的设想,应该是一个线程里面可以连接多个客户端响应,比如在一个线程内用Winsock控件数组之类的东东,每个线程整个至少20个元素的控件数组,一个线程服务20个客户端连接,这样应该才是逻辑上可行的。不晓得IIS6支持多少同时连接了。</p>
<p>看来我服务程序用的地方应该改成不要保持活动连接才成,不然,整个几千个活动连接的话,服务器一定会受不了的。</p>
<p>刚刚边写上面这些文字,边测试&nbsp;&nbsp;<font face="Verdana">PowerTCP_Winsock_ActiveX_Trial.exe</font>&nbsp; ,发现另一个问题,在客户端一直处于活动状态,并且有数据流动的时候,&nbsp;<font face="Verdana">PowerTCP_Winsock_ActiveX_Trial.exe</font> 的TCP控件响应&nbsp; .Close 异常缓慢,不晓得是由于工作于线程中还是什么别的原因,只要我用单线程+Timer控件数组模拟的多连接客户端一直处于活动状态,</p>
<p><font face="Verdana">Set mySock_mTh(i) = Nothing '卸载线程。</font></p>
<p>这里就一直处于半阻塞状态,也可能是我在后面还加了 <font face="Verdana">DoEvents</font> 的缘故了。但是不加 <font face="Verdana">DoEvents</font> 的话,创建和卸载线程时,主界面会卡住,感觉不好。</p>
<p>最后。。。由于&nbsp;&nbsp;<font face="Verdana">PowerTCP_Winsock_ActiveX_Trial.exe</font>&nbsp; 是收费的 $399&nbsp; ..贵的在承受范围之外了。。。。找到的那些所谓的注册机都用不成。。看来下一步得研究 SockAPI 了。。&nbsp;<font face="Verdana">PowerTCP_Winsock_ActiveX_Trial.exe</font>&nbsp; 只能起到证明VB ActiveX单元多线程内多连接服务的可实现性。。。。。</p>
<p>明天要去海口开会,得过几天再回来研究了,搞不好又去三亚玩两天就得到星期一才能出现了。。。。。</p>
我是晶晶

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2009-11-10 23:38:35 | 显示全部楼层
<p>我在想,使用VB6来做具有高压力的服务器端程序应该不是一个好选择.......</p>
<p>&nbsp;</p>
<p>我建议你看一下MASM,这种宏汇编语法与VB极为接近,而且你也是函数式编程习惯了的,上手应该不是问题.</p>
<p>&nbsp;</p>
<p>微软在易用性方面,下了巨大的工夫.......</p>
<p>&nbsp;</p>
<p>另外,线程一般是一个"池",一个线程里对应的是多个连接,要是一个线程一个连接,就太浪费了,而且确实也如你所说,线程多到一定程度,CPU消耗在多个线程间的切换时间,就有可能已经比单个线程的工作时间长了,那时候效率将急剧下降,得不偿失啊.........</p>
<p>&nbsp;</p>
<p>我这几天写代码也写得巨头痛,逻辑上本身没啥问题,结果出现一些古怪的软故障,一天出个那么一两次,虽然不影响工作,但是老解决不了,丢脸啊....</p>
<p>&nbsp;</p>
<p>打算重写相关的流程部分,好好分析一下可能的原因.....头痛.</p>
我就是嗷嗷叫的老马了......

3

主题

50

回帖

0

精华

银牌会员

积分
444
发表于 2009-11-12 00:17:46 | 显示全部楼层
<p>今早起床打算出门了,结果才下床就肾绞痛,肾结石闹的。。疼的要命,还好家在医院附近,去医院紧急处理到下午才好了点,去海口也去不成了,刚刚退了机票,现在暂时好了点,又回来继续研究。</p>
<p>'---------------------------------------------</p>
<p>程序逻辑结构太复杂了问题就莫名其妙了,我八年前写了一个程序用于电话拨号连接单片机通讯的,牵扯的小问题一大堆,写好基本能用之后就一直用着,前两天想拿出来优化一下改改,结果代码就看的头大,当时VB6刚刚接触,写的比较生分,只好作罢。。。。。。</p>
<p>&nbsp;</p>
<p>一般情况下,我是先大概设计好框架,再补齐各个功能模块的代码,画个程序流程草图应该是有帮助的,便于分析各个功能模块逻辑和其他问题。</p>
<p>&nbsp;</p>
<p>刚刚我看老马你的“<font face="Verdana">模拟WINSOCK控件的一个自定义控件</font>”想将它包装成一个单独Ocx时,无意中翻到MSDN里面的 Winsock控件的一些说明,其中有一条:</p>
<p>“在 ConnectionRequest 事件中使用<font face="Verdana"> <b>Accept</b> 方法。”,我就郁闷了,于是测试了如下代码:</font></p>
<p>'-------------------------------------------</p>
<p><font face="Verdana">Option Explicit</font></p>
<p><font face="Verdana">&nbsp;&nbsp;&nbsp; Dim rID As Long<br/>&nbsp;&nbsp;&nbsp; <br/>Private Sub Command1_Click()<br/>&nbsp;&nbsp;&nbsp; Winsock1.Close<br/>&nbsp;&nbsp;&nbsp; Winsock1.LocalPort = 3000<br/>&nbsp;&nbsp;&nbsp; Winsock1.Listen<br/>&nbsp;&nbsp;&nbsp; Timer1.Enabled = True<br/>&nbsp;&nbsp;&nbsp; Label1.Caption = "Listen Port:3000 ."<br/>End Sub</font></p>
<p><font face="Verdana">Private Sub Command2_Click()<br/>&nbsp;&nbsp;&nbsp; Winsock1.Close<br/>&nbsp;&nbsp;&nbsp; Winsock2.Close<br/>&nbsp;&nbsp;&nbsp; Timer1.Enabled = False<br/>&nbsp;&nbsp;&nbsp; Label1.Caption = "Stop Listen ."<br/>End Sub</font></p>
<p><font face="Verdana">Private Sub Timer1_Timer()<br/>&nbsp;&nbsp;&nbsp; If rID &lt;&gt; 0 Then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Winsock2.Accept rID<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rID = 0<br/>&nbsp;&nbsp;&nbsp; End If<br/>End Sub</font></p>
<p><font face="Verdana">Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)<br/>&nbsp;&nbsp;&nbsp; rID = requestID<br/>End Sub</font></p>
<p>'-----------------------------------------</p>
<p>结果,Winsock2.Accept rID 这里直接报错 10038,客户端表现就是那天那样的闪断闪断,由此,我推测,在两个线程之间传递 requestID&nbsp; 之后,比这里在一个线程内传递还离得远多了,由此可以说明,.Accept&nbsp; 不能工作于ConnectionRequest之外。这个问题就头大了。。。。。<br/></p>
<p>而 <font face="Verdana">PowerTCP_Winsock_ActiveX_Trial.exe</font>&nbsp; 是将 <font face="Verdana">Daemon</font><font face="Verdana">.Accept</font> 当作变量传递给接收应答的 TCP.socket 属性里面</p>
<p>TCP.<font face="Verdana">Socket</font>= Daemon<font face="Verdana">.Accept</font> '这样运作的。只是不晓得他传递出来这个 Daemon<font face="Verdana">.Accept</font> 是个什么值了。跟踪了一下感觉应该是传递了类似 <font face="Verdana">Winsock的.SocketHandle值。但是在WinSock里面&nbsp; SocketHandle 好像是只读的啊。</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
我是晶晶

3

主题

50

回帖

0

精华

银牌会员

积分
444
发表于 2009-11-12 11:50:31 | 显示全部楼层
<p>昨晚夜里睡了睡不着,忽然想到个馊主意来实现Winsock的多线程运用,昨晚太冷就没敢起来测试代码,今早测试了一次,编译成ActiveX之后,Winsock也可以用于多线程了。不必再用什么 PowerTcp或SockAPI了。直接使用VB6的Winsock就成了,爽。</p>
<p>秘诀就是 Accept 和<font face="Verdana">requestID</font>都不离开 <font face="Verdana">ConnectionRequest</font> 事件,多余的代码都不用。</p>
<p>试了几百连接一切正常,线程之间就不会出现阻塞问题了。线程还是不用太多。我觉得最多开100个线程就够用了。而且也不会像PowerTcp那样无法卸载线程失控。</p>
<p>每个线程30几个连接应该是能伺候的。这样就是100×30 =3000客户端同时连接应该可以轻松伺候了。只是内存占用稍微大了点,到了30几M,不过运行在服务器上不影响。</p>
<p>下面应该就是把我拿个服务程序的全部东东整个移植过来这个多线程ActiveX里面就成了。</p>
我是晶晶

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2009-11-12 17:14:40 | 显示全部楼层
<p>........身体第一啊!!</p>
<p>&nbsp;</p>
<p>别折腾那么狠,兄弟.</p>
<p>&nbsp;</p>
<p>编程是爱好,也可能是工作,可能是任何的事,但绝对不应该是玩命的.........</p>
我就是嗷嗷叫的老马了......

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2009-11-12 17:27:55 | 显示全部楼层
<p>在 ConnectionRequest 事件中使用<font face="Verdana"> <b>Accept</b> 方法。</font></p>
<p>&nbsp;</p>
<p>啊,这个逻辑居然没想透!!</p>
<p>&nbsp;</p>
<p>仔细想想,确实是这样的.</p>
<p>&nbsp;</p>
<p>如果脱离了这个事件,这个ID是否有效,居然没有去考虑这一层的逻辑.</p>
<p>&nbsp;</p>
<p>思路啊思路............有时候一个思路能救地球...........-_-b</p>
我就是嗷嗷叫的老马了......

3

主题

50

回帖

0

精华

银牌会员

积分
444
发表于 2009-11-12 19:28:50 | 显示全部楼层
<div class="msgheader">QUOTE:</div><div class="msgborder"><b>以下是引用<i>马大哈</i>在2009-11-12 17:14:40的发言:</b><br/>
<p>........身体第一啊!!</p>
<p>&nbsp;</p>
<p>别折腾那么狠,兄弟.</p>
<p>&nbsp;</p>
<p>编程是爱好,也可能是工作,可能是任何的事,但绝对不应该是玩命的.........</p></div>
<p>多谢老马关心。。。。。。这个病是结石忽然移动闹的,倒是和编程关系不大,</p>
<p>不过这几天在老马你指导下研究这个多线程收获多多,现在解决了Winsock的多线程使用问题就一切好办了。</p>
<p>本来这个是我一个朋友他们单位的一个额外服务部门用的服务程序,以前有个家伙用VC写了个运行效率不错,就是经常非法操作,自动关闭。</p>
<p>后来写程序那个家伙升迁了,也就不好在嘛烦人家来改了。</p>
<p>几个月前的一天过去玩,本来是去教他用GoogleMap API做一个气象信息定点显示的东东的,结果聊起这个让它头大的程序来,就问我VB能不能做,我之前也没做过Winsock运用的程序,只玩过MSComm,于是就告诉他我查查资料做做看看,应该可以做,查了用Winsock实现多链接的服务端的做法,就做了个演示程序给他看看,感觉可行,还不错,于是一路就这样做下来了。</p>
<p>我一直以为VB的Timer控件数组是并发的,虽然之前也知道VB程序是单线程的,但是在Timer控件里面代码不多执行快的话,给人感觉就是并发,我对Timer控件数组抱的幻想有点大,知道前几天他打电话来说是有的客户端一直得不到服务器的回应,我才郁闷起来,代码经过几次修正已经没有问题了啊,无奈我也找不出问题来,只好做个一个内部代码运行的跟踪日志文件出来,跟踪那个没有收到服务器应答的客户端,结果发现,在启动Timer控件数组中的那个元素后,它居然没有按照预定的 <font face="Verdana">.Interval</font>&nbsp; 来启动,而是延后了不固定的好长一段时间,才想起来VB的单线程,于是测试了几次Timer控件的内部阻塞发现,Timer不管你一个窗口放几个,都只相当与一个,因为任何一个都会阻塞其他的运行,无奈才想起用多线程来做做看看,找到Blog里面那个多线程例子才有了希望,API多线程是实现不了这个的,于是才有了这几天的研究。。。</p>
<p>我之前还向那个朋友吹嘘说是“并发”的,这下只好打自己嘴巴了。现在就是改改,将那个在用的服务程序包装成多线程的再拿去测试效率了。这个工作有点费时间。对于我来说,编程主要是爱好,因为工作不是做这个的,纯属业余爱好,帮朋友做这个程序也是友情支持,当然,他把我算在他课题组里面也给了我一点报酬。</p>
<p>不过最重要的是要做好给他用,因为这个程序属于他课题里面一个组件,课题目前还没结题。程序的修改也主要是我主动发现漏洞,慢慢修改,现在改成多线程这个倒是不忙了,我慢慢做,前几天删了Timer控件数组改给他那个也在稳定的运行中了。。。</p>
<p>&nbsp;</p>
<p>再次感谢老马这几天来的指导,整完后,我发个动态多线程的例子出来算是这几天研究成果了。</p>
<p>&nbsp;</p>
我是晶晶

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

论坛牛人贡献奖关注奖最佳版主进步奖人气王疯狂作品奖精英奖赞助论坛勋章乐于助人勋章

QQ
发表于 2009-11-12 21:07:39 | 显示全部楼层
<p>指导不敢当.....我也只是从MSDN中挖出这个方法做了个例子与说明而已,让更多的人知道VB6其实有官方的多线程方案存在,只是形式不同而已....</p>
<p>&nbsp;</p>
<p>而把这个方案实际应用的却是你们呢,哈哈.</p>
<p>&nbsp;</p>
<p>并且从这次这个事情中我也学习了很多的东西,比如这个Accept方法的调用细节问题,就反映了我平时太粗心大意,竟然没有想到这个,还老在猜测是否这就是传说中的"非线程安全"所造成的------------其实就应用来说,没有太多的"非线程安全"例子,主要就是这个WINSOCK,估计大家都是没注意.</p>
<p>&nbsp;</p>
<p>而现在,其中的奥秘才被你找出来了,这真的要替大家感谢你!</p>
<p>&nbsp;</p>
<p>这是对VB6使用者的福音</p>
我就是嗷嗷叫的老马了......

0

主题

3

回帖

0

精华

初来乍到

积分
0
发表于 2009-11-20 08:56:07 | 显示全部楼层
我也遇到了同样的问题,想知道最后怎么解决的

3

主题

50

回帖

0

精华

银牌会员

积分
444
发表于 2009-11-21 20:09:44 | 显示全部楼层
我也遇到了同样的问题,想知道最后怎么解决的
zzd1000 发表于 2009-11-20 08:56


不晓得你说的是什么问题,如果是楼主的问题,那么老马已经给出了很好的解决办法,目前我的多线程多连接winsock程序基本转型完毕,可以投入使用了。这几天单线程winsock服务器多客户端转型到多线程多连接多客户端中间遇到一些问题,解决了一部分,我重新开一贴和大家交流了。

0

主题

8

回帖

0

精华

初来乍到

积分
19
发表于 2010-5-5 21:27:53 | 显示全部楼层
好东西要支持!!










你一定要体验的游戏,很不错问道推广人
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

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