技术宅的结界

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

QQ登录

只需一步,快速开始

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

【VB6】直接使用CreateThread创建多线程的探究

[复制链接]

50

主题

256

帖子

8393

积分

用户组: 管理员

UID
77
精华
15
威望
174 点
宅币
7527 个
贡献
187 次
宅之契约
0 份
在线时间
205 小时
注册时间
2014-2-22
发表于 2022-5-23 20:36:05 | 显示全部楼层 |阅读模式

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

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

x
大家都听过“VB6程序不支持多线程”的流言,但大多数人并没有真的测试过。刚才我写了个DEMO测试了一下,发现这是一个“半真半假”的流言,VB6直接使用CreateThread创建多线程是可行的,只不过条件比较苛刻。
.png

先上结论:
游客,如果您要查看本帖隐藏内容请回复
测试代码:
游客,如果您要查看本帖隐藏内容请回复
回复

使用道具 举报

1093

主题

2661

帖子

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
238
威望
606 点
宅币
22186 个
贡献
46077 次
宅之契约
0 份
在线时间
2128 小时
注册时间
2014-1-26
发表于 2022-5-24 00:42:31 | 显示全部楼层
那我还用 VB6 干嘛……

0

主题

20

帖子

563

积分

用户组: 大·技术宅

UID
7437
精华
0
威望
112 点
宅币
209 个
贡献
110 次
宅之契约
0 份
在线时间
20 小时
注册时间
2021-9-11
发表于 2022-5-24 06:30:23 | 显示全部楼层
本帖最后由 tlwh163 于 2022-5-24 07:12 编辑

认真学习

看到以前的学习笔记 说是在线程函数的第一行 插入下面的语句 就可以完美多线程

楼主可以验证一下:

CreateIExprSrvObj 0&, 4&, 0& '加到线程函数的第一句

评分

参与人数 2威望 +110 宅币 +110 贡献 +110 收起 理由
Golden Blonde + 100 + 100 + 100 太TM牛逼了。
0xAA55 + 10 + 10 + 10 屌!

查看全部评分

1093

主题

2661

帖子

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
238
威望
606 点
宅币
22186 个
贡献
46077 次
宅之契约
0 份
在线时间
2128 小时
注册时间
2014-1-26
发表于 2022-5-24 12:32:39 | 显示全部楼层
tlwh163 发表于 2022-5-24 06:30
认真学习

看到以前的学习笔记 说是在线程函数的第一行 插入下面的语句 就可以完美多线程


牛逼!我照着你给的这个东西搜索了一下,发现了这个帖子:

https://www.vbgood.com/forum.php?mod=viewthread&tid=92847

函数声明如下:

  1. Public Declare Function CreateIExprSrvObj Lib "msvbvm60.dll" (ByVal p1_0 As Long, ByVal p2_4 As Long, ByVal p3_0 As Long) As Long
复制代码


按照原帖子的内容:

1.不需要写tlb库(感觉麻烦了,使用tlb主要是防止vb设置err.lastDllerr),
2.不需要处理tls(很多都是暴力copy,不知道有没有后遗症?)
3.不需要编译成activx exe(这东东会在注册表留下垃圾项,从VB的引用中会看到),
4.不需要编译成p-code(P代码的坏处众所周知了)
5.不需要干掉 setSysXXXerr(干掉后 err.lastDllErr肯定无效啦,不爽)
6.不需要远程创建线程...(汗,谁发明的,好厉害,转了好大一个圈)


那就只需要上锁就可以安全多线程了。这一下就都清晰了。

不过具体还是要测试了才知道好不好用。

50

主题

256

帖子

8393

积分

用户组: 管理员

UID
77
精华
15
威望
174 点
宅币
7527 个
贡献
187 次
宅之契约
0 份
在线时间
205 小时
注册时间
2014-2-22
 楼主| 发表于 2022-5-24 14:56:42 | 显示全部楼层
tlwh163 发表于 2022-5-24 06:30
认真学习

看到以前的学习笔记 说是在线程函数的第一行 插入下面的语句 就可以完美多线程


这句真是神来之笔!

经测试,在线程函数开头加上这句之后,MsgBox还是不可以用,但是对象的部分属性和方法可以访问了,而且更多的内置函数可以用了(比如Hex$)。

最主要是,不用编译为P-CODE了!!!

点评

这个只是能让子线程执行API调用,并没有完整初始化。像MsgBox等GUI的东西需要完整初始化了可以(需要注意完整初始化了后果是子线程也会执行Sub Main)  发表于 2022-5-24 19:08

0

主题

2

帖子

17

积分

用户组: 初·技术宅

UID
7859
精华
0
威望
2 点
宅币
11 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2022-5-24
发表于 2022-5-24 15:56:36 | 显示全部楼层
这个方案支持IDE下调试吗

点评

要想在IDE下安全调试线程代码,那只有写ActiveX.DLL或ActveX.EXE,ActiveX.DLL的单元线程模式支持被C/C艹(或其它语言)写的程序用多个线程同时调用。  发表于 2022-5-24 19:22

50

主题

256

帖子

8393

积分

用户组: 管理员

UID
77
精华
15
威望
174 点
宅币
7527 个
贡献
187 次
宅之契约
0 份
在线时间
205 小时
注册时间
2014-2-22
 楼主| 发表于 2022-5-24 17:42:09 | 显示全部楼层
W741 发表于 2022-5-24 15:56
这个方案支持IDE下调试吗


极有可能会崩溃。如果要在IDE里调试程序,建议在启动线程之前加上App.LogMode进行判断,多线程相关的代码只有在编译后才运行。

7

主题

145

帖子

7313

积分

用户组: 真·技术宅

UID
4293
精华
5
威望
414 点
宅币
5516 个
贡献
799 次
宅之契约
0 份
在线时间
229 小时
注册时间
2018-9-19
发表于 2022-5-24 19:16:52 | 显示全部楼层
tlwh163 发表于 2022-5-24 06:30
认真学习

看到以前的学习笔记 说是在线程函数的第一行 插入下面的语句 就可以完美多线程

提示一下,这么用是有内存泄露的,正确的用法是:
Declare Function CreateIExprSrvObj Lib "msvbvm60" (Optional ByVal Reserved As Long, Optional ByVal Size As Long = 4, Optioanl ByVal Fail As Boolean) As IUnknown

Function 线程入口函数(ByVal 线程参数 As Long) As Long
        Dim eso As IUnknown
        Set eso = CreateIExprSrvObj() '提示:需要用IUnknown类型局部变量保存此对象,这样可以在入口函数的作用域生命周期结束后自动释放。
        … … '你真的线程处理代码
End Function

50

主题

256

帖子

8393

积分

用户组: 管理员

UID
77
精华
15
威望
174 点
宅币
7527 个
贡献
187 次
宅之契约
0 份
在线时间
205 小时
注册时间
2014-2-22
 楼主| 发表于 2022-5-24 22:44:13 | 显示全部楼层
系统消息 发表于 2022-5-24 19:16
提示一下,这么用是有内存泄露的,正确的用法是:
Declare Function CreateIExprSrvObj Lib "msvbvm60" ( ...


我去,VB6太神奇了,竟然还可以定义不存在的类型。。。

话说在ExitThread之前无需加一句【Set eso = Nothing】么?

点评

所以,我建议用 Err.Raise 来代替 ExitThread,然后做子线程的入口函数用On Error GoTo 捕获异常,然后返回错误码,这样实现退出线程,就能保证正确回栈。  发表于 2022-5-25 10:23
不是不存在,而是这是VB的隐藏类型(提示不显示),IUnknown在stdole2.tlb里面。ExitThread的问题,我认为是巨硬自身SB的问题,ExitThread函数没有做回栈处理  发表于 2022-5-25 10:19

30

主题

207

帖子

2463

积分

用户组: 版主

UID
1821
精华
7
威望
69 点
宅币
1877 个
贡献
206 次
宅之契约
0 份
在线时间
397 小时
注册时间
2016-7-12
发表于 2022-5-24 23:51:48 | 显示全部楼层
美俪女神 发表于 2022-5-24 22:44
我去,VB6太神奇了,竟然还可以定义不存在的类型。。。

话说在ExitThread之前无需加一句【Set eso = Not ...

定义不存在的类型会当作一个类的指针

1093

主题

2661

帖子

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
238
威望
606 点
宅币
22186 个
贡献
46077 次
宅之契约
0 份
在线时间
2128 小时
注册时间
2014-1-26
发表于 2022-5-25 17:22:27 | 显示全部楼层
系统消息 发表于 2022-5-24 19:16
提示一下,这么用是有内存泄露的,正确的用法是:
Declare Function CreateIExprSrvObj Lib "msvbvm60" ( ...

如何“完整初始化”?我想在子线程里面也能 MsgBox

7

主题

145

帖子

7313

积分

用户组: 真·技术宅

UID
4293
精华
5
威望
414 点
宅币
5516 个
贡献
799 次
宅之契约
0 份
在线时间
229 小时
注册时间
2018-9-19
发表于 2022-5-25 18:27:00 | 显示全部楼层
0xAA55 发表于 2022-5-25 17:22
如何“完整初始化”?我想在子线程里面也能 MsgBox

你想想ActiveX.DLL是怎么实现的多线程初始化?是不是要先DllMain,然后再DllGetClassObject获取对象,而ActiveX.DLL的这俩函数又是调用msvbvm60.dll的VBUserDllMain和VBUserDllGetClassObject,所以是不是可以在标准exe里面调用这俩来完整初始化?
之前,我这网上找到过别人用这方法来初始化的,我试过确实就可以MsgBox和使用Form了,但是要注意VB6那“胎神”会每个线程都会执行一次 Sub Main。

1093

主题

2661

帖子

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
238
威望
606 点
宅币
22186 个
贡献
46077 次
宅之契约
0 份
在线时间
2128 小时
注册时间
2014-1-26
发表于 2022-5-25 20:49:40 | 显示全部楼层
系统消息 发表于 2022-5-25 18:27
你想想ActiveX.DLL是怎么实现的多线程初始化?是不是要先DllMain,然后再DllGetClassObject获取对象,而A ...

噗 确实这也是一种变身为“胎神”的方式(

1

主题

115

帖子

130

积分

用户组: 小·技术宅

UID
7535
精华
0
威望
0 点
宅币
15 个
贡献
0 次
宅之契约
0 份
在线时间
9 小时
注册时间
2021-10-16
发表于 2022-5-26 09:20:50 | 显示全部楼层
论坛有你真的精彩~

本版积分规则

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

GMT+8, 2022-7-1 13:39 , Processed in 0.052055 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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