多线程与VB







--------------------------------------------------------------------------------


“协作式多任务”、“抢占式多任务”、“多进程”、“多线程”这些词真可以算是如雷贯耳了,不过词是词,了解是了解,两回事。我曾经煞有介事的向一个同学说明什么是“多进程”,什么是“多线程”,不多久就发现我的解释是完全错了的,所以现在我要讲的是 β2 版,有什么错误敬请提出。 

先说说“协作式多任务”和“抢占式多任务”。在 Windows 3.1 中,多任务方式是“协作式多任务”,意思是说一个任务得到了 CPU 时间,除非它自己放弃使用 CPU ,否则将完全霸占 CPU ,所以任务之间需要协作——使用一段时间的 CPU ,放弃使用,其它的任务也如此,才能保证系统的正常运行;而在 Windows 95 中使用的就是“抢占式多任务”了,它的总控制权在 Windows 手中,Windows 会轮流询问每一个任务是否需要使用 CPU ,需要使用的话就让它用,不过在一定时间后,Windows 会剥夺当前任务的 CPU 使用权,把它排在询问队列的最后,再去询问下一个任务……。这种方式上的不同造成 95 和 3.1 性能上的不同:3.1 中如果有一个任务死锁,则系统也同样死锁;95 中有一个任务死锁,系统仍能正常运行。 

再说说“多进程”和“多线程”。同一个程序的多个运行的副本就是“多进程”了;在 Windows 95 中,一个进程只是一段放置程序的内存,只有线程才是真正运行的任务,所以一个进程至少包含一个线程,事实上,系统为每一个进程创建一个缺省线程,叫做主线程,主线程可以创建子线程,子线程仍然可以再创建子线程,这就是“多线程”了。Windows 对待线程是一视同仁的都作为一个任务看待的,并不对主线程有什么优惠,这和 OS/2 稍有不同:Windows 下一个进程中只要有一个线程在运行就不终止,但在 OS/2 下主线程结束时会同时关闭所有的子线程。有一个同事对 OS/2 的这种线程管理方式很赞赏,我却不以为然,我以为让线程自然的结束会比强制结束好的多。 

Windows 3.1 是没有“多线程”的概念的,因为没有意义,只有在“抢占式多任务”的方式下,“多线程”才有其用武之地。 

“多线程”的“Hello World”是文件复制。在进行一个大文件的复制时,虽然复制窗体上有一个“取消”按钮,但如果不是多线程,就只有到了文件复制完毕时程序才知道用户按了“取消”钮,典型的先斩后奏,非我所欲也。当然也不是完全没有办法解决,在 VB 中是用“DoEvents”,C 中是用“PeekMessage”,不过在“协作式多任务”中这实在是一个危险的办法——此函数不知道什么时候返回,但是硬件不等人,所以也只是没有办法的办法,何况即使在“抢占式多任务”,这样做的效率也是很低的。而用“多线程”,可以用一个线程执行“疯狂拷贝”,一个线程监视按钮状态,在用户按下了“取消”按钮时,程序马上就可以知道,并且马上“取消”了。 

“多线程”的说明到此为止,以下我要说一说 VB 的多线程问题。 

官方的文件说 VB 不支持多线程,这其实是说 VB 中的语句并不都是线程安全的,但是哪些是线程安全的,他们不说,我们也不知道,只有靠实践,我还没有实践,所以也不知道。但是这并不是说 VB 程序真的是“单线程”的程序,事实上至少每一个 ActiveX 控件都是一个线程,所以如果大家对 ActiveX 控件没有我这样的恶感,大可开发一个 ActiveX 控件实现安全的多线程程序。至于 VB 缺省的控件是否也是用多线程实现的,我还不知道,各位如有兴趣,可以测试一下。 

在我做的多线程的例子里曾说过 VB 提供的“CreateThread”函数的说明是错误的,关键在“函数地址”那一项使用了缺省的“ByRef”,而实际应该是“ByVal”的。此函数第一个参数是指定新线程的属性,产生安全描述符用的,可以传一个“NULL”过去,表示不在乎,我在我的例子里就是这样做的;第二个参数指定新线程的栈大小,也可以传一个“0”过去,说明和主线程一样;第三个参数是函数地址,用“AddressOf”得到;第四个是参数指针;第五个是创建标志,缺省值是“NULL”,表示立即执行,可斟酌使用;最后一个是用来返回线程的线程标识符。 

新线程函数定义为“Function 线程函数(ByVal 参数 As Long) As Long”。“CreateThread”函数的参数一般情况下用缺省值就可以了,但是如果想传递参数到新线程,C 不用说,指针是它的长项,只是在 VB 中,虽然可以用“VarPtr”函数取得变量地址,但是这个地址对于 VB 程序本身却几乎是无用的,就是“线程函数”中得到的那个“参数”几乎是无用的。我说几乎是无用的,就是说事实上还是有用的。 如果有很多参数要传递,使用“CopyMemory”是可以实现的,不过,这绝对是一个危险函数,不到不得已不用也罢;但是如果只需要传递一个小于 32 位的值,我们就可以大张旗鼓的用这个“参数”了——虽然系统说此参数是指针,不过传入传出以及解释权都是由你控制,谁也不能阻止你将一个“Long”按值传递给“线程函数”,甚至如果你希望传递的是一个“Single”,也只需要修改“CreateThread”和“线程函数”的说明即可,不用我多说了吧!当然,最简单的方法有时候最有效——用全局变量,没有限制,只是有些麻烦。 

对 VB 来说,简单的多线程程序还需要用到“ExitThread”,一般还要用到“SuspendThread”、“ResumeThread”,这几个函数相对简单的多,就不多说了。不过如果是复杂的多线程,就要用到一些线程同步的 API 了,我还没有用到,总不能空穴来风,所以也不说了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值