找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 11349|回复: 12

[原创]如何在VB6里面实现稳定的多线程(VB6.0代码)

 火.. [复制链接]

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

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

QQ
发表于 2008-3-10 12:19:39 | 显示全部楼层 |阅读模式
<font face="Verdana">微软官方给出的方案在MSDN里面有说,就是使用ActiveX EXE那种"单元线程模型".<br/><br/>我也曾经试过,的确可以实现"多线程",只是由于要多一个EXE,比较麻烦,后来就没有深入了.<br/><br/>结果一次无意中在VBGOOD中看到一段代码,才打通了一个关节:为什么不直接使用ActiveX EXE写程序呢?!<br/><br/>那段代码里面,是直接使用这种工程类型,然后在工程内使用CreateObject来生成一个新对象,这样的话,新的对象就工作于一个单元线程内了.<br/><br/>其实这个我也知道,可是就没有想到在ActiveX EXE内部使用 <img style="MARGIN-TOP: 0px; MARGIN-LEFT: 0px; MARGIN-RIGHT: 0px" alt="" src="http://www.m5home.com/blog/images/smilies/27.gif" border="0" -2px? 0px="0px" 0px?/><br/><br/>看来思路真的不如人.....还要多多学习,多多积累.<br/><br/>ActiveX EXE工程设置为"独立启动"后,貌似只能从Sub Main里进行初始化.<br/><br/>而每个对象的建立,都会调用一次这个过程,因此这个过程需要一次性运行.<br/><br/>但是MSDN里说得很清楚,在单元线程模型里面,全局变量的范围只能是本单元,因此不能使用设置全局变量来完成这个过程的一次运行逻辑.<br/><br/>原代码里使用了GetProp等方式,感觉不是很好,于是作了一下改进,使用事件对象来完成此工作.<br/><br/>Sub Main相关代码如下:
<div class="dp-highlighter">
<ol class="dp-vb">
<li class="alt"><span><span class="keyword">Private</span><span>&nbsp;</span><span class="keyword">Const</span><span>&nbsp;MyEvent&nbsp;</span><span class="keyword">As</span><span>&nbsp;</span><span class="keyword">String</span><span>&nbsp;=&nbsp;</span><span class="string">"m5home"</span><span>&nbsp;&nbsp;</span></span></li>
<li class=""><span></span><span class="keyword">Dim</span><span>&nbsp;hEvent&nbsp;</span><span class="keyword">As</span><span>&nbsp;</span><span class="keyword">Long</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;</span></li>
<li class=""><span></span><span class="keyword">Sub</span><span>&nbsp;Main() &nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">If</span><span>&nbsp;GetEventHandle&nbsp;=&nbsp;0&nbsp;</span><span class="keyword">Then</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">'由于每个新对象的建立,都要执行Main()过程,因此使用事件对象来进行判断. </span><span>&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hEvent&nbsp;=&nbsp;CreateEvent(0&amp;,&nbsp;</span><span class="keyword">False</span><span>,&nbsp;</span><span class="keyword">False</span><span>,&nbsp;MyEvent)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">'在单元线程下,模块里的全局变量已经没有用了. </span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frmMain.Show &nbsp;&nbsp;</span></li>
<li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">End</span><span>&nbsp;</span><span class="keyword">If</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span></span><span class="keyword">End</span><span>&nbsp;</span><span class="keyword">Sub</span><span>&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;&nbsp;</span></li>
<li class="alt"><span></span><span class="keyword">Private</span><span>&nbsp;</span><span class="keyword">Function</span><span>&nbsp;GetEventHandle()&nbsp;</span><span class="keyword">As</span><span>&nbsp;</span><span class="keyword">Long</span><span>&nbsp;&nbsp;</span></span></li>
<li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;GetEventHandle&nbsp;=&nbsp;OpenEvent(EVENT_ALL_ACCESS,&nbsp;</span><span class="keyword">False</span><span>,&nbsp;MyEvent) &nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">Call</span><span>&nbsp;CloseHandle(GetEventHandle) &nbsp;&nbsp;</span></span></li>
<li class=""><span></span><span class="keyword">End</span><span>&nbsp;</span><span class="keyword">Function</span><span>&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;</span></li>
<li class=""><span></span><span class="keyword">Public</span><span>&nbsp;</span><span class="keyword">Function</span><span>&nbsp;Quit() &nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">Call</span><span>&nbsp;CloseHandle(hEvent) &nbsp;&nbsp;</span></span></li>
<li class=""><span></span><span class="keyword">End</span><span>&nbsp;</span><span class="keyword">Function</span><span>&nbsp;&nbsp;</span></span></li></ol></div>
<p><textarea class="vb" style="DISPLAY: none" name="code" rows="15" cols="100">Private Const MyEvent As String = "m5home"
Dim hEvent As Long

Sub Main()
&nbsp;&nbsp;&nbsp;&nbsp;If GetEventHandle = 0 Then&nbsp;&nbsp;&nbsp;&nbsp; '由于每个新对象的建立,都要执行Main()过程,因此使用事件对象来进行判断.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hEvent = CreateEvent(0&amp;, False, False, MyEvent)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'在单元线程下,模块里的全局变量已经没有用了.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frmMain.Show
&nbsp;&nbsp;&nbsp;&nbsp;End If
End Sub

Private Function GetEventHandle() As Long
&nbsp;&nbsp;&nbsp;&nbsp;GetEventHandle = OpenEvent(EVENT_ALL_ACCESS, False, MyEvent)
&nbsp;&nbsp;&nbsp;&nbsp;Call CloseHandle(GetEventHandle)
End Function

Public Function Quit()
&nbsp;&nbsp;&nbsp;&nbsp;Call CloseHandle(hEvent)
End Function</textarea><br/><br/>由于事件对象是系统范围的,因此可以比较完美的完成这个工作.<br/><br/>同时事件对象在进程消失后,会自动释放,也方便<br/><br/>示例代码可以生成一个新的单元线程,并在这个线程里面显示一个窗体,窗体进行一个大循环.<br/><br/>循环内没有放入DoEvents函数,因此会造成循环所在窗体无响应.<br/><br/>而此时主窗体不受影响.<br/><br/>对象间可以通过一般的调用与事件来进行通讯.<br/><br/>完整的代码,在此下载:</p>
<p>&nbsp;</p>
<p><a href="http://www.m5home.com/blog/article.asp?id=54">http://www.m5home.com/blog/article.asp?id=54</a></font></p>
我就是嗷嗷叫的老马了......

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

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

QQ
 楼主| 发表于 2008-7-11 14:35:51 | 显示全部楼层
<p>做一个对象数组,用CreateObject加载这些对象即可.</p>
我就是嗷嗷叫的老马了......

1

主题

2

回帖

0

精华

初来乍到

积分
286
发表于 2008-11-5 09:02:38 | 显示全部楼层
<p>请问一下,如果我要加载n个线程怎么做?</p>

0

主题

3

回帖

0

精华

初来乍到

积分
212
发表于 2009-4-15 14:50:06 | 显示全部楼层
<div class=quote><b>以下是引用<i>马大哈</i>在2008-7-11 14:35:51的发言:</b><br>
       
        <p>做一个对象数组,用CreateObject加载这些对象即可.</p>
       
</div><p></p>

请教几个问题
1 Dim WithEvents I As cMT 是不能用数组定义的,怎么用数组创建呢

2 新建的线程如何修改一个公共的变量 ,比如说就是frmmain可以读取的公共数组呢?

3 能否不用窗体实现多线程 ,例如我有个 function gethttp(url)as string 函数



你的代码怎样修改可以只让这个函数实现多线程而不用加载窗体,以便增加速度呢,最好可以每个线程的数据都放在一个公共数组内




我现在的方法是,比如说想用200个线程,我定义并创建了200次然后销毁,这个过程中,主窗体还是不能响应的



另外加楼主qq说让用临时会话,但是你有禁止了临时会话,怎么和你联系呢?
[此贴子已经被作者于2009-4-15 14:50:39编辑过]

0

主题

3

回帖

0

精华

初来乍到

积分
212
发表于 2009-4-15 15:00:26 | 显示全部楼层
你的qq加好友答案是什么呢

0

主题

3

回帖

0

精华

初来乍到

积分
212
发表于 2009-4-15 15:02:27 | 显示全部楼层
我想实现如下效果

定义 all(200) as string 数组
定义  function gethttp(url)as string 函数

然后创建 200个线程

每个线程都用gethttp函数获得内容让在all(200)内


恳请楼主指导一下,能否顺便写个示例,其他代码尽可能的少,我来测试一下效率,看看怎么样

0

主题

19

回帖

0

精华

铜牌会员

积分
255
发表于 2009-5-30 08:22:34 | 显示全部楼层
<p>多线程,感觉总是不稳定</p>

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

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

QQ
 楼主| 发表于 2009-5-30 20:12:32 | 显示全部楼层
<div class="msgheader">QUOTE:</div><div class="msgborder"><b>以下是引用<i>dabingrain</i>在2009-5-30 8:22:34的发言:</b><br/>
<p>多线程,感觉总是不稳定</p></div>
<p>研究VB6下面的多线程的人本身就不多.</p>
<p>&nbsp;</p>
<p>能做稳定的就更少了.</p>
我就是嗷嗷叫的老马了......

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

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

QQ
 楼主| 发表于 2009-4-23 23:28:35 | 显示全部楼层
<div class="msgheader">QUOTE:</div><div class="msgborder"><b>以下是引用<i>ttyy6</i>在2009-4-15 14:50:06的发言:</b><br/>
<p></p>请教几个问题 1 Dim WithEvents I As cMT 是不能用数组定义的,怎么用数组创建呢 2 新建的线程如何修改一个公共的变量 ,比如说就是frmmain可以读取的公共数组呢? 3 能否不用窗体实现多线程 ,例如我有个 function gethttp(url)as string 函数 你的代码怎样修改可以只让这个函数实现多线程而不用加载窗体,以便增加速度呢,最好可以每个线程的数据都放在一个公共数组内 我现在的方法是,比如说想用200个线程,我定义并创建了200次然后销毁,这个过程中,主窗体还是不能响应的 另外加楼主qq说让用临时会话,但是你有禁止了临时会话,怎么和你联系呢?
<div align="right"><font color="#000066">[此贴子已经被作者于2009-4-15 14:50:39编辑过]</font></div></div>
<p>第一个问题,"<strong>Dim WithEvents I As cMT 是不能用数组定义的,怎么用数组创建呢</strong>"</p>
<p>&nbsp;</p>
<p>使用数组并还要处理事件,VB6里是不能直接定义的,需要一点小技巧.</p>
<p>&nbsp;</p>
<p>先写个类,在这个类里面完成你需要声明事件的那个对象的代码,也就是说事件在这个"包装类"里面.</p>
<p>&nbsp;</p>
<p>然后使用普通数组方式定义这个类即可,每个对象在这个包装类里面是可以处理各自的事件的,而包装类又不存在事件的问题.</p>
<p>&nbsp;</p>
<p>虽然占内存多了些,但不失为一种折中的方案.</p>
<p>&nbsp;</p>
<p>第二个问题,"<strong>新建的线程如何修改一个公共的变量 ,比如说就是frmmain可以读取的公共数组呢</strong>?"</p>
<p>&nbsp;</p>
<p>由于VB6的线程是单元内的线程,因此公共变量虽然能访问,但仅能访问线程创建时的那份"复本",即,真正的公共变量即便被改变了,在线程的"单元房间"内,还是只能看到这个"线程房间"创建时的那个公共变量的复本.</p>
<p>&nbsp;</p>
<p>因此要在多线程里面访问公共变量是比较麻烦的.</p>
<p>&nbsp;</p>
<p>折中方案又来了:</p>
<p>&nbsp;</p>
<p>你可以把一个类声明到模块里,再在各线程创建后,将此类的实例传进去,让各个线程直接访问这个对象.</p>
<p>&nbsp;</p>
<p>可以看出,这样做虽然能达到公共变量的访问与共享,但却由于线程间调度频繁,效率比较低,尽量地少用吧.</p>
<p>&nbsp;</p>
<p>第三个问题,"<strong>能否不用窗体实现多线程 ,例如我有个 function gethttp(url)as string 函数 你的代码怎样修改可以只让这个函数实现多线程而不用加载窗体,以便增加速度呢</strong>"</p>
<p>&nbsp;</p>
<p>单元里面,可以放的东西是COM规范的东西,所以,无论是窗体,还是类的实例,都是可以放进去的.</p>
<p>&nbsp;</p>
<p>只要你在创建实例时,使用CreateObject即可.</p>
<p>&nbsp;</p>
<p>用它创建的对象,就已经在另一个"单元"里面了.</p>
<p>&nbsp;</p>
<p>另,我的QQ确实是满了,没办法....可以加我MSN:&nbsp;&nbsp;&nbsp;&nbsp; myjian01(##)yahoo.com.cn </p>
<p>&nbsp;</p>
<p>你也可以加我的群:</p>
<p>&nbsp;</p>
<p>10413004</p>
<p>&nbsp;</p>
<p>请注明在论坛上的ID即可</p>
我就是嗷嗷叫的老马了......

76

主题

375

回帖

0

精华

铜牌会员

积分
231
发表于 2010-6-18 01:42:29 | 显示全部楼层

1

主题

11

回帖

0

精华

初来乍到

积分
13
发表于 2010-10-7 03:35:22 | 显示全部楼层
换成 ActiveX DLL 行不行?

275

主题

3017

回帖

1

精华

管理员

嗷嗷叫的老马

积分
17064

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

QQ
 楼主| 发表于 2010-10-7 10:46:30 | 显示全部楼层
换成 ActiveX DLL 行不行?
tingyan 发表于 2010-10-7 03:35



    貌似不可以

1

主题

11

回帖

0

精华

初来乍到

积分
13
发表于 2010-10-7 11:19:29 | 显示全部楼层
貌似不可以
马大哈 发表于 2010-10-7 10:46



    谢谢
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

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