技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 1403|回复: 9
收起左侧

【VB6】多线程讨论终结贴:使用ActiveX-EXE实现完美的多线程

[复制链接]

52

主题

278

帖子

8938

积分

用户组: 管理员

UID
77
精华
16
威望
237 点
宅币
7860 个
贡献
246 次
宅之契约
0 份
在线时间
226 小时
注册时间
2014-2-22
发表于 2022-10-16 23:59:17 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

x
如何在VB6里实现稳定多线程,一直是网上争论不休的话题。网上基本上有两派,第一派是通过修补VB程序的机器码和调用特定函数来实现多线程。但是经我测试,无论哪个版本、无论作者号称多么稳定,其实都是不稳定的。我前段时间做了个《坦克大战》,使用单线程时非常稳定,而使用网上大神们的“魔改多线程”时,玩不到20分钟程序就会卡死或崩溃。而第二派,就是使用ActiveX-EXE实现多线程。网上对ActiveX-EXE实现多线程的稳定性没有质疑,但是在其它方面有诸多指责,比如说在ActiveX-EXE程序里,句柄不能共享,全局变量不能用等等。其实这些指责里,一半是谣言,一半是误解(因为没有搞清楚ActiveX-EXE的多线程特性造成的)。

在讨论多线程之前,先讨论一下,VB里什么物件是全局的?所有人都会说:窗体对象是全局的,模块是全局的,全局变量和常量也是全局的。但是“全局物件”又有两层含义,第一层是,写在任何地方的代码都可以直接访问它们,第二层是,它们没有“分身”。这时有人要说了,你唠唠叨叨说这些废话跟多线程有什么关系呢?我必须指出的是,VB里没有任何“自带物件”在进程内是全局的,它们仅是在线程内全局。一旦新建了线程,并且当新线程访问这些全局物件时,所有的物件都会给访问它的线程创造一个“分身”。即使是模块里的全局函数也不例外。举一个例子:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <windows.h>

  4. long StaticTest()
  5. {
  6.         static long v = 0;
  7.         return ++v;
  8. }

  9. DWORD WINAPI ThreadProc(LPVOID lpParameter)
  10. {
  11.         printf("[%ld]%ld\n",GetCurrentThreadId(),StaticTest());
  12.         return 0;
  13. }

  14. int _cdecl main(int argc, char **argv)
  15. {
  16.         CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
  17.         Sleep(500);
  18.         CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
  19.         Sleep(500);
  20.         CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
  21.         system("pause");
  22.         return 0;
  23. }
复制代码
这段C程序的三次输出,应该分别是1、2、3。但如果用VB的AvtiveX-EXE写同样的代码,它们的输出分别是1、1、1!因为正如我上面所说,虽然在代码里,StaticTest函数是全局的,但是ActiveX-EXE的每一个线程里,它们都有自己独立的StaticTest!看懂了上文,你就会明白为什么会有“ActiveX-EXE里连句柄都不能共享”的谣言:因为即使是全局变量,线程A根本就无法直接访问到线程B的全局变量。但是这个句柄只要产生,它在进程里就是有效的。你只要想办法把线程A产生的句柄值让线程B得知即可。这里面的方法太多了,小白用SaveSetting/GetSetting、驱动老哥用DOS头的废弃空间、学院派用文件映射,不管什么方法,能达成目标就行。此外,某个线程要访问其它线程的变量和窗口/类是可行的,但必须用指针,指针的值也可以同样用上述方法传递。

接下来解释在ActiveX-EXE里玩多线程的具体步骤。首先你要新建一个模块,写一个Sub Main。任何ActiveX-EXE的代码都从Sub Main开始执行,这点对于习惯了C语言的人都很好理解。在Sub Main里你要创建一个主窗口,让Sub Main的代码尽快结束。这一步是必须的,因为创建多个线程的代码在Sub Main里无效,因此接下来的代码只能写在窗口里。需要注意的是,由于任何线程在启动的时候都会执行一次Sub Main,因此你要在Sub Main里设置一个“事件”,防止你的初始化代码被重复执行。接下来就是关于多线程代码的核心步骤了:新建一个类模块,但这个类模块只是一个“药引”,它唯一的作用是在Class_Initialize里Load一个窗口(这个窗口被称为“多线程代码窗口”)。在“多线程代码窗口”里,你要放置一个Interval为1的Timer1,在Timer1_Timer里,先写一句Timer1.Enabled = False。在这句之后,才写你自己的代码。当线程执行完毕要退出时,简单一句Unload Me即可。
  1. Private Sub Timer1_Timer()
  2.     Timer1.Enabled = False
  3.     MsgBox CStr(App.ThreadID), , "tid"
  4.     Unload Me
  5. End Sub
复制代码

当创建新线程的时候,只需要三行代码:
  1. Dim o As Object
  2. Set o = CreateObject("app.class")
  3. Set o = Nothing
  4. '//其实你可以把这三行理解为:
  5. 'HANDLE h;
  6. 'h = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
  7. 'CloseHandle(h);
复制代码

最后稍微解释一下怎么让ActiveX-EXE正确运行,需要修改两个设置:
1.png
2.png
需要注意的是,多线程效果只有在编译为EXE后才有效:
0.png

完整DEMO代码:
游客,如果您要查看本帖隐藏内容请回复

评分

参与人数 1威望 +10 宅币 +30 贡献 +30 收起 理由
0xAA55 + 10 + 30 + 30 屌!

查看全部评分

回复

使用道具 举报

1096

主题

2694

帖子

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
240
威望
679 点
宅币
23055 个
贡献
46153 次
宅之契约
0 份
在线时间
2190 小时
注册时间
2014-1-26
发表于 2022-10-17 10:05:08 | 显示全部楼层
以前一直没有注意到 ActiveX-EXE 有“独立模式”“每个对象对应一个线程”这两个选项。

但“系统消息”有告诉过我“VB6的正常多线程应该是线程之间隔离的,互相之间不能访问到对方的数据。”

看样子你这样就是最“正规”的VB6创建多线程的方式,而且你也遇到了“每个新线程都要进入 Sub Main()”的现像。

祝你考试成功



7

主题

155

帖子

9104

积分

用户组: 真·技术宅

UID
4293
精华
5
威望
424 点
宅币
7247 个
贡献
829 次
宅之契约
0 份
在线时间
263 小时
注册时间
2018-9-19
发表于 2022-10-18 10:55:14 | 显示全部楼层
我是第三派,使用Active.DLL来做多线程,因为VB6的Active.DLL支持被多线程调用,dll导出一个类模块作为线程入口即可,然后VC那边写个exe来执行CreateThread,然后每个线程里面各自创建一个类模块的对象实例并调用其入口方法就好了。

1

主题

127

帖子

280

积分

用户组: 中·技术宅

UID
7535
精华
0
威望
0 点
宅币
153 个
贡献
0 次
宅之契约
0 份
在线时间
23 小时
注册时间
2021-10-16
发表于 2022-10-25 08:23:49 | 显示全部楼层
啥也不说了,感谢楼主分享哇!

0

主题

12

帖子

43

积分

用户组: 初·技术宅

UID
2974
精华
0
威望
2 点
宅币
27 个
贡献
0 次
宅之契约
0 份
在线时间
7 小时
注册时间
2017-10-18
发表于 2022-10-26 14:23:18 | 显示全部楼层
先感谢再看!感谢!!

0

主题

26

帖子

90

积分

用户组: 小·技术宅

UID
2399
精华
0
威望
0 点
宅币
64 个
贡献
0 次
宅之契约
0 份
在线时间
24 小时
注册时间
2017-4-12
发表于 2022-10-31 22:35:00 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

0

主题

7

帖子

21

积分

用户组: 初·技术宅

UID
3274
精华
0
威望
2 点
宅币
10 个
贡献
0 次
宅之契约
0 份
在线时间
1 小时
注册时间
2017-12-29
发表于 2022-11-18 15:14:01 | 显示全部楼层
用过的请发言

0

主题

7

帖子

37

积分

用户组: 初·技术宅

UID
6296
精华
0
威望
6 点
宅币
18 个
贡献
0 次
宅之契约
0 份
在线时间
1 小时
注册时间
2020-10-9
发表于 2022-11-20 15:40:47 | 显示全部楼层
太吊了,虽然现在已经不用VB6了

0

主题

10

帖子

43

积分

用户组: 初·技术宅

UID
7859
精华
0
威望
2 点
宅币
29 个
贡献
0 次
宅之契约
0 份
在线时间
3 小时
注册时间
2022-5-24
发表于 2022-11-21 09:48:57 | 显示全部楼层
每天拜一拜大佬,保佑我的技术突飞猛进

0

主题

48

帖子

61

积分

用户组: 小·技术宅

UID
8099
精华
0
威望
2 点
宅币
9 个
贡献
0 次
宅之契约
0 份
在线时间
8 小时
注册时间
2022-10-22
发表于 2022-11-23 23:02:03 | 显示全部楼层
感谢楼主分享!

本版积分规则

QQ|申请友链||Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2022-12-9 03:05 , Processed in 0.185472 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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