这一天,我低着脑袋正迷糊着呢,忽然有个顶盔掼甲的家伙,径直朝我走了过来。
这家伙手握缰绳,牵着一匹高头骏马,到我近前就詈骂道:“你这小斯怎地如此惫懒!还不速速起身!”
我一头雾水,弱弱地问了一句:“又谁惹您不痛快了?”
那个家伙一顿抱怨,说道:
”自从主公(刘备)封了五人为五虎上将,关将军(关羽)就对此十分不满。
他对黄老将军(黄忠)也被封为五虎之一颇有意见,早已不念战长沙时与黄老将军两人惺惺相惜之情,如今着实地看不起这年逾七旬的老卒。
而黄老将军也不服老啊,总是想证明自己宝刀未老,尚能上阵杀敌。
两个人就这么你不服我不忿,一来一回总是明里争暗里斗。
这不前几日这老二位不知哪里又来的兴致,突然又要打赌比赛、一决高下。
如今见着了赵将军(赵云),硬是也要拉上他一起赌赛。
这次不比武,换作赛马了,并约在三日之后在579.7高地,以谁先到山顶为胜。
你速速把马匹送去营地,快去快回,莫要耽搁!“
我打了个哈欠,悻悻地接过绳子,暗骂道:”喵了个咪,真是吃饱了撑的!撸代码多带劲!“
边走边骂,可是山路崎岖,没走多远,也不知怎地,这马好好的大路不走,自己就非要往那树丛中钻。
我见势不妙,立刻追赶上去,哪晓得不知深浅,竟一脚踩空跌落尘埃......
“啊啊啊!~“当时我就一身白毛汗!
定了定神,揉了揉眼,才发现是一场南柯之梦!
怎么撸着代码就瞌睡了?还好不是在上班时间,真心累啊!
不过说到这儿,我不禁思考起来,如何实现类似于多人赛马这种功能呢?
通常传统的VB6方式是添加多个 Timer
控件,但如果业务逻辑更加复杂或追求高性能高效率的话,显然不太专业也不太现实。
自己水平不够怎么办?好办,向大神学习啊!
还好以前拜读过几位大神关于《VB6多线程技术超详细示例(纯API)》的文章。
具体网址已不可考,但应该尚存于VB贴吧中,有心人可以去找找看。
古老的VB6曾被很多人诟病,其一便是无法实现多线程功能,其实这是一种误解,它强大得很呢!
经过在旧资料里的一番查找,囫囵地学习和了解后,整理总结如下一些简要知识内容,请诸君参考。
一、使用VB6多线程的必备知识储备
- 熟练VB6的基本语法
- 能熟练的使用API
- 熟知
BYVAL
和BYREF
的区别 - 大致了解消息循环
- 最好能懂一点点指针和各种数据在内存中的存在方式
- 大致了解线程与进程的关系和区别,了解多线程的特点和意义
二、使用VB6多线程,保证其稳定性的注意事项
- VB6多线程程序在IDE下的稳定性和子类化相当,编译为EXE后才具有完整的稳定性
- VB6多线程程序必须以
SUB MAIN
作为启动对象 - 由于是用的是
ACTIVEX EXE
的初始化流程(但是工程类型必须选择标准EXE!),所以必须在SUB MAIN
中处理重入问题(模版中已经写好了) - VB6主线程(就传统的拖控件,在事件里面写代码的那个线程)不要先于子线程退出,否则容易发生难以预料的情况
- 不要在子线程中直接定义定长数组(例如
Dim arr(100) AS LONG
),否则将导致程序崩溃。如果一定要在子线程中直接定义定长数组,请用Redim
(例如Redim arr(100) AS LONG
)代替 - 多个线程在程序逻辑上有可能会同时操作同一块内存时(新手可以理解为同时操作同一变量或HDC之类的东东时),要特别注意加锁。(原子操作不必加锁,详情请百度)即使用临界区排队处理,否则易导致数据混乱甚至程序崩溃。但是
DOEVENTS
不能进入临界区,否则易造成相关的线程锁死。
三、大神提供了一个VB6多线程模板程序,所有实现多线程功能均依照这个模板来扩展实现,具有如下特点
- 稳定:采用的是微软官方藏起来的,对
VB6 ACTIVEXEXE
多线程环境进行初始化的一套流程。 - 高效:可以编译为本机代码运行,而不是龟速
PCODE
。优化选项可以随意勾选,保证了执行效率。 - 方便快捷:限制较少,所有的工作都可以在一个工程内全部完成。对API的声明既可以用
TLB
也可以用VB6最传统的Declare XXX
。生成的EXE在自带有VB6运行库的任何WINDOWS系统上都可运行,就多线程技术本身而言无需额外注册其它组件,且生成的程序可以被加壳。 - 参考资料易得:由于是系统API创建的多线程,绝大部分的技术原理和C系列语言的多线程是相通的。完全可以参考C的相关技术和代码。这对以后想学C系列语言的爱好者们来说是个很好的适应性“热身运动”。
- 实用,学习成本低:这是以上四个特点的综合。有一定编程功力的爱好者能很快上手,学习成本远低于另外再学一门语言,而且很多内容都是所有的多线程技术本来就都要学习的。并且该套方法继承了VB6快速开发的初衷和特点,具有很强的实用性。
太棒了!有了大神们加持护佑,我依葫芦画瓢做了个简易版的赛马演示程序。
程序只做简单的功能演示,作为学习参考用,在文末有下载。
部分关键代码:
' VBMTRun 线程实际执行模块
Public Sub Thread1() '子线程1
'**************(重要!)VB6线程环境初始化*************
' VB6运行库初始化
CreateIExprSrvObj 0&, 4&, 0&
' COM组件初始化
CoInitializeEx ByVal 0&, ByVal (COINIT_MULTITHREADED Or COINIT_SPEED_OVER_MEMORY)
' 诱导VB6运行库内部其他部分的初始化
InitVBdll
'**************(重要!)VB6线程环境初始化*************
' 业务逻辑内容
......
' 业务逻辑内容
' 卸载COM组件(省掉也不会影响稳定性,但可能造成句柄或内存泄漏。为了养成好习惯,还是写上)
CoUninitialize
End Sub
' 窗体模块
' 启动线程
VBThreadHandle1 = CreateThread(ByVal 0&, ByVal 0&, AddressOf VBMTRun.Thread1, ByVal 0&, ByVal CREATE_DEFAULT, VBThreadID1)
' 终止线程
TerminateThread VBThreadHandle1, ByVal 0&
' 释放句柄
CloseHandle VBThreadHandle1
在此再次感谢大神们的杰出贡献,为你们点赞,向你们致敬!
时间不早已是夜里11点多,为了惜命千万不能熬夜!
我打了个哈欠,爬上了床,拿起手机想看看还有没有谁在线,微信屏幕上赫然写着一行小字。
关云长“拍了拍”你......
演示程序下载链接:https://o8.cn/4QzIVu 密码:78cx
关注微信公众号,免费分享下载我收集的资料。
下载链接:https://pan.baidu.com/s/1iN7joxUo3Yu7QL2NYqUUtg 提取码:
★扫码关注公众号, 发送【000752】获取阅读密码
WeChat @网管小贾
Blog @www.sysadm.cc