如何在VB6里面实现稳定的多线程
作者:admin 日期:2008-02-25
微软官方给出的方案在MSDN里面有说,就是使用ActiveX EXE那种"单元线程模型".
我也曾经试过,的确可以实现"多线程",只是由于要多一个EXE,比较麻烦,后来就没有深入了.
结果一次无意中在VBGOOD中看到一段代码,才打通了一个关节:为什么不直接使用ActiveX EXE写程序呢?!
那段代码里面,是直接使用这种工程类型,然后在工程内使用CreateObject来生成一个新对象,这样的话,新的对象就工作于一个单元线程内了.
其实这个我也知道,可是就没有想到在ActiveX EXE内部使用
看来思路真的不如人.....还要多多学习,多多积累.
ActiveX EXE工程设置为"独立启动"后,貌似只能从Sub Main里进行初始化.
而每个对象的建立,都会调用一次这个过程,因此这个过程需要一次性运行.
但是MSDN里说得很清楚,在单元线程模型里面,全局变量的范围只能是本单元,因此不能使用设置全局变量来完成这个过程的一次运行逻辑.
原代码里使用了GetProp等方式,感觉不是很好,于是作了一下改进,使用事件对象来完成此工作.
Sub Main相关代码如下:
由于事件对象是系统范围的,因此可以比较完美的完成这个工作.
同时事件对象在进程消失后,会自动释放,也方便:)
示例代码可以生成一个新的单元线程,并在这个线程里面显示一个窗体,窗体进行一个大循环.
循环内没有放入DoEvents函数,因此会造成循环所在窗体无响应.
而此时主窗体不受影响.
对象间可以通过一般的调用与事件来进行通讯.
完整的代码,在此下载:
点击下载此文件
**************************改一下,添加一个简单测试例子***********************

点击下载此文件
我也曾经试过,的确可以实现"多线程",只是由于要多一个EXE,比较麻烦,后来就没有深入了.
结果一次无意中在VBGOOD中看到一段代码,才打通了一个关节:为什么不直接使用ActiveX EXE写程序呢?!
那段代码里面,是直接使用这种工程类型,然后在工程内使用CreateObject来生成一个新对象,这样的话,新的对象就工作于一个单元线程内了.
其实这个我也知道,可是就没有想到在ActiveX EXE内部使用

看来思路真的不如人.....还要多多学习,多多积累.
ActiveX EXE工程设置为"独立启动"后,貌似只能从Sub Main里进行初始化.
而每个对象的建立,都会调用一次这个过程,因此这个过程需要一次性运行.
但是MSDN里说得很清楚,在单元线程模型里面,全局变量的范围只能是本单元,因此不能使用设置全局变量来完成这个过程的一次运行逻辑.
原代码里使用了GetProp等方式,感觉不是很好,于是作了一下改进,使用事件对象来完成此工作.
Sub Main相关代码如下:
复制内容到剪贴板
程序代码

Private Const MyEvent As String = "m5home"
Dim hEvent As Long
Sub Main()
If GetEventHandle = 0 Then '由于每个新对象的建立,都要执行Main()过程,因此使用事件对象来进行判断.
hEvent = CreateEvent(0&, False, False, MyEvent) '在单元线程下,模块里的全局变量已经没有用了.
frmMain.Show
End If
End Sub
Private Function GetEventHandle() As Long
GetEventHandle = OpenEvent(EVENT_ALL_ACCESS, False, MyEvent)
Call CloseHandle(GetEventHandle)
End Function
Public Function Quit()
Call CloseHandle(hEvent)
End Function
Dim hEvent As Long
Sub Main()
If GetEventHandle = 0 Then '由于每个新对象的建立,都要执行Main()过程,因此使用事件对象来进行判断.
hEvent = CreateEvent(0&, False, False, MyEvent) '在单元线程下,模块里的全局变量已经没有用了.
frmMain.Show
End If
End Sub
Private Function GetEventHandle() As Long
GetEventHandle = OpenEvent(EVENT_ALL_ACCESS, False, MyEvent)
Call CloseHandle(GetEventHandle)
End Function
Public Function Quit()
Call CloseHandle(hEvent)
End Function
由于事件对象是系统范围的,因此可以比较完美的完成这个工作.
同时事件对象在进程消失后,会自动释放,也方便:)
示例代码可以生成一个新的单元线程,并在这个线程里面显示一个窗体,窗体进行一个大循环.
循环内没有放入DoEvents函数,因此会造成循环所在窗体无响应.
而此时主窗体不受影响.
对象间可以通过一般的调用与事件来进行通讯.
完整的代码,在此下载:

**************************改一下,添加一个简单测试例子***********************


评论: 24 | 引用: 0 | 查看次数: 9271


我想做一个可以一边记录信息,一边将已经记录好的信息用FTP进行传输的程序,请问,你有什么好的办法吗?
admin 于 回复

这个功能不需要什么特殊的地方吧.
信息的记录与FTP上传,没有冲突啊!
你可以设置为定时+定量上传,比如30分钟内如果有新内容就上传,以及如果新内容超过500K就上传.
信息的记录与FTP上传,没有冲突啊!
你可以设置为定时+定量上传,比如30分钟内如果有新内容就上传,以及如果新内容超过500K就上传.


如果要是把要执行的代码放到一个自定义控件中,然后用地址函数取得执行状态,在用load 创建控件数组来实现呢,应该是可靠的吧,必竟active可以设置为独立的嘛
admin 于 回复

没有明白你的意思.....


老马,在赞一个啊


不错不错!下载回去好好研究一下哈~~~


如果将主窗体的参数传递给新线程或者使用全局变量,就会导致主窗体卡死,有办法解决吗?
admin 于 回复

除非你是调用了另一线程中的过程,而这个过程是耗时的,未处理完前不返回,那样的话肯定会挂起啊.
这种情况比较方便的是使用一个定时器,在调用过程中存储参数,并启动定时器,让过程立即返回.
然后定时器触发后再调用真正的处理过程.......
这种情况比较方便的是使用一个定时器,在调用过程中存储参数,并启动定时器,让过程立即返回.
然后定时器触发后再调用真正的处理过程.......


感谢您的这篇文章,但是我还是有点问题。我比如想在界面上有个文本框,里面的数字,从1变到1000000
怎么写,才能不影响界面?
多指教!
admin 于 回复
怎么写,才能不影响界面?
多指教!

如果仅仅是这个功能,那好象没有必要使用多线程吧.


这种方法无法在MDI工程里使用,可惜
admin 于 回复

这没办法,MDI窗体好象有个什么数据共享还是什么之类的问题,比较麻烦,所以微软干脆禁止了MDI窗体在多线程工程中的使用.....


其实本质上来说,单元线程模型是介于多线程和多进程之间的。
之所以采用线程,主要就是为了共享存储空间和减小开销。否则还不如采用多进程。
admin 于 回复
之所以采用线程,主要就是为了共享存储空间和减小开销。否则还不如采用多进程。

大量使用时的开销的确很大,特别是在线程间调度的操作比较多的时候.
我一般是用于UI分离,达到不挂起UI的效果即可......
我一般是用于UI分离,达到不挂起UI的效果即可......



为什么在线程里不能实现winsock.accept
测试了下,建立不了连接
测试了下,建立不了连接
WINSOCK内部貌似是多线程实现的
你只要保证你的数据处理过程不会卡死就不需要多线程处理.
至于这个连接问题,有可能是你代码的问题,我的第二个例子就是使用WINSOCK做下载的示例,没有发现你所说的问题.


线程里的winsock.accept状态为7.客户端仍处理正在连接状态


为什么在线程里不能实现winsock.accept
测试了下,建立不了连接
测试了下,建立不了连接



msgbox会卡死二边
应该做到只卡一面
自己做一个MSGBOX窗体?
应该做到只卡一面
自己做一个MSGBOX窗体?


msgbox会卡死二边
应该做到只卡一面
自己做一个MSGBOX窗体?
应该做到只卡一面
自己做一个MSGBOX窗体?


关于这份代码多开的解决方案请见: http://www.m5home.com/bbs/dispbbs.asp?boardid=27&Id=2557



请问我要加载N个线程应该怎么做?
建立多个对象即可
把对象生成一个数组,使用CreateObject来初始化.


请问我要加载N个线程应该怎么做?



什么破过滤
没办法,机器人太多了.添加了不少广告方面的过滤.
我可不想我的BLOG变成广告页.


什么破过滤


不错
确实增加了一个线程
主窗口也不卡
确实增加了一个线程
主窗口也不卡


卡死了?不可能吧.
别告诉我你没编译?
IDE环境是单线程的哦,别搞错了.
别告诉我你没编译?
IDE环境是单线程的哦,别搞错了.


你的超大循环把I窗体卡死了,同时也主窗体卡死了。。。。。


这个就不清楚了...一直在VB6里编程,多线程一点都不熟
多线程有些什么调试手段,也不知道...

多线程有些什么调试手段,也不知道...


你的demo像是不好调试的.
http://blog.m5home.com/article.asp?id=65
将会挂起的操作放在一个类里,并添加一个事件,用于操作完成后触发调用者.
再用CreateObject创建对象,则它就在另一线程中了.
主线程调用后就返回,然后等待操作完成的事件.