请选择 进入手机版 | 继续访问电脑版

玩酷之家

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 852|回复: 0

稳定方便实用的VB6多线程技术

[复制链接]

92

主题

97

帖子

361

积分

中级会员

Rank: 3Rank: 3

积分
361
发表于 2018-3-17 21:38:38 | 显示全部楼层 |阅读模式

一、VB6天生就支持多线程的论证、证据和历史:

网上一直有流传了将近十年的谣言,说VB6天生就不支持多线程。很久以前我也信以为真了,直到发现了老马写的ACTIVEXEXE多线程示例(示例压缩包中已附带)。稍作研究后发现这是微软官方本来就有提供的多线程方案。只不过这种标准方法使用起来很麻烦,参考资料十分稀少。造成了多年以来无人问津甚至有人听都没听说过。所以正确的说法应该是“VB6多线程实现起来有点麻烦”或者“支持的不太好”。说“天生就不支持”显然过分至极。就像VB6的类没有C++和JAVA的灵活,并且一个自定义类就要用一个文件,类多了加载文件都得卡一会。这时,只能说“VB6对类的支持不太好,用起来有点麻烦”,如果有人说“VB6天生就不支持类”那就闹笑话了,用起来有点麻烦不等于没有。

进一步研究后发现,我们,哪怕是刚入门的菜鸟们,都在无意之中用VB6写出了多线程程序。比如你在窗口加个WMP(windows media player)控件做播放器,编译为EXE后,你会发现任务管理器里面,你的程序的线程数绝对不是1了。VB6写出的程序是标准的WIN32程序,放到WIN10下面,系统都不敢说“这不是有效的WIN32程序”,而使其良好运行。能够拥有多个线程是所有WIN32程序的“天赋”。

真正对VB6有限制的是它必须依赖VB6运行库,就像.net程序必须要netframework一样(由于VB6历史悠久,所有的非极端阉割版系统都自带VB6运行库,而.net就不一定了)。用API的方式创建的子线程由于没有初始化运行库,编译出来的程序,除了加减乘除什么也不能做。于是有段时间很流行PCODE大法,似乎这种方式能让子线程和主线程共享部分运行库。但是不能解决根本问题并且执行效率拙计!

直到前几年,VBGOOD论坛的老汉(ID:download)发现了微软未公开的初始化运行库的函数,以及诱导相关组件完全初始化的方法。能编译为本机代码稳定运行的VB6多线程技术成为了可能。本套技术示例就用到了这些函数。

由于是纯API进行线程操作,IDE并不知道我们使用了多线程,所以多数情况下需要编译为EXE运行后才有完整的稳定性和真实的效果(其实GDI+和子类化又何尝不是如此,调试时稍不注意就闪退!)。这会带来调试上的些许麻烦,关于这方面的调试技巧,在第6个示例中有说明。


本套VB6多线程方法有如下特点:

1、稳定:采用的是微软官方藏起来未公开的,对VB6 ACTIVEXEXE多线程环境进行初始化的一套流程。
区别是这套流程在API新建的子线程中运行了,而不是在操作麻烦的ACTIVEXEXE中。
此外,没有使用内嵌汇编,外部调用自制DLL等方法。是“纯天然”的VB6多线程。

2、高效:可以编译为本机代码运行,而不是龟速PCODE。优化选项可以随意勾选,保证了执行效率。

3、方便快捷:限制较少,所有的工作都可以在一个工程内全部完成。对API的声明既可以用TLB也可以用VB6最传统的Declare XXX。
生成的EXE在自带有VB6运行库的任何WINDOWS系统上都可运行,就多线程技术本身而言无需额外注册其它组件,且生成的程序可以被加壳。

4、参考资料易得:由于是系统API创建的多线程,绝大部分的技术原理和C系列语言的多线程是相通的。完全可以参考C的相关技术和代码。
这对以后想学C系列语言的爱好者们来说是个很好的适应性“热身运动”。

5、实用,学习成本低:这是以上四个特点的综合。有一定编程功力的爱好者能很快上手,学习成本远低于另外再学一门语言,
而且很多内容都是所有的多线程技术本来就都要学习的。并且该套方法继承了VB6快速开发的初衷和特点,具有很强的实用性。


使用VB6多线程的必备知识储备:
1、熟练VB6的基本语法
2、能熟练的使用API
3、熟知BYVAL和BYREF的区别
4、大致了解消息循环
5、最好能懂一点点指针和各种数据在内存中的存在方式
6、大致了解线程与进程的关系和区别,了解多线程的特点和意义(这些纯理论的知识在百度上很容易找到,主要是上面几点需要时间掌握。)


使用VB6多线程,保证其稳定性的注意事项:

1、VB6多线程程序在IDE下的稳定性和子类化相当,编译为EXE后才具有完整的稳定性
2、VB6多线程程序必须以SUB MAIN作为启动对象(在在工程——属性——启动对象中自行设置)
3、由于是用的是ACTIVEXEXE的初始化流程(但是工程类型必须选择标准EXE!),所以必须在SUBMAIN中处理重入问题(模版中已经写好了)
4、VB6主线程(就传统的拖控件,在事件里面写代码的那个线程)不要先于子线程退出,否则容易发生难以预料的情况
5、不要在子线程中直接定义定长数组(例如dim arr(100) as long),否则将导致程序崩溃。
在子线程调用的子过程?子函数?对象?类中定义定长数组不会有任何问题?
直接使用之前在标准模块(BAS)中定义好的公有定长数组也没问题。
如果一定要在子线程中直接定义定长数组,请用REDIM(例如Redim arr(100) as Long)代替
6、多个线程在程序逻辑上有可能会同时操作同一块内存时(新手可以理解为同时操作同一变量或HDC之类的东东时),要特别注意加锁。(原子操作不必加锁,详情请百度)

即使用临界区排队处理,否则易导致数据混乱甚至程序崩溃。但是DOEVENTS不能进入临界区,否则易造成相关的线程锁死。

再次感谢为VB6多线程技术做出贡献的老马、老汉、IZERO、TGY等等前辈们

特别是老汉(VBGOOD论坛的Download),没有他发现的微软藏起来的函数,方便、快速的VB6多线程技术就没法实现!


【最新版】稳定、方便、实用的VB6多线程技术(附老马的ActiveX多线程示例).7z (55.93 KB, 下载次数: 184)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|玩酷之家 ( 鄂ICP备14012049号-1 )

GMT+8, 2018-12-12 15:21 , Processed in 0.170801 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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