在VB中实现多线程

Author: Escapism Date: 2000年 第39期

    通常,我们所编写的应用程序在执行的时候,32位的操作系统(如Win9X/WinNT系列)对于每一个调入内存的应用程序都只产生一个拥有独立的虚拟地址空间和相对独立的消息队列的进程,而每一个进程在没有特别指出时都仅拥有一个执行实体——线程。然而,在编写一些需要长时间等待的操作(如存盘操作或网络传输等等),或者是复杂的操作的应用程序时,使用单线程往往会使得程序由于进行长时间等待而使系统等待的时间过长。CPU长时间处于空闲状态,从而影响程序执行的效率。这时如果使用多线程就可以充分地利用系统资源,使程序的效率得到提高。
    非常遗憾的是,VB中并没有直接提供创建多线程的方法,幸好Windows API提供了这样的函数来让我们对线程的创建和设置进行控制。在下面的例子中,将会对多线程的使用进行简单的介绍,需要使用到的Windows API函数有CreateThread()创建线程、ResumeThread()——继续线程、SetThreadPriority()——设置线程属性(设置线程的优先级)、GetThreadPnority()——得到线程属性(线程的优先级)、SuspendThread()——挂起线程、TerminateThread()——结束线程。限于篇幅API函数的具体声明不再一一列出,具体可以参考API文本浏览器。需要注意的是CreateTHread()函数是在调用函数的进程的虚拟地址空间内创建线程,如果要在其他进程的虚拟地址空间内创建线程,如果要在其他进程的虚拟地址空间内创建线程则需要使用CreateRemoteThread()函数。
    在VB中我们新建一个工程,一个类模块和其他程序中需要使用的部件。将类模块命名为NewThreads,其余各部分的属性可根据实际情况进行设置。在类模块中加入以下代码:
    Private Type userThread
        Handle As Long
        Enabled As Boolean
    End Type
    Private uThread As userThread
    Private Const CREATE_SUSPENDED As Long = & H4
    private Const THREAD_BASE_PRIORITY_IDLE As Long = -15
    private Const THREAD_BASE_PRIORITY_LOWRT As Long = 15
    private Const THREAD_BASE_PRIORITY_MAX As Long = 2
    private Const THREAD_BASE_PRIORITY_MIN As Long = -2
    private Const THREAD_PRIORITY_HIGHEST As Long = THREAD_BASE_PRIORITY_MAX
    private Const THREAD_PRIORITY_LOWEST As Long = THREAD_BASE_PRIORITY_MIN
    private Const THREAD_PRIORITY_ABOVE_NORMAL As Long = (THREAD_PRIORITY_HIGHEST -1)
    private Const THREAD_PRIORITY_BELOW_NORMAL As Long = (THREAD_PRIORITY_LOWEST +1)
    private Const THREAD_PRIORITY_IDLE As Long = THREAD_BASE_PRIORITY_IDLE
    private Const THREAD_PRIORITY_NORMAL As Long = 0
    private Const THREAD_PRIORITY_TIME_CRITICAL As Long =  THREAD_BASE_PRIORITY_LOWRT'        //初始化(构造函数)//
    Public Sub Initialize (ByVal lpfnBasFunc As Long)
    Dim lStackSize As Long, lCreationFlags As Long,lpThreadId As Long,lNull As Long
    On Error Resume Next
    lNull = 0
    lStackSize = 0
    lCreationFlags = CREATE_SUSPENDED
    '//创建新的线程//
    uThread,Handle =   CreateThread(lNull,  lStackSize,lpfnBasFunc,lNull,lCreationFlags,lpThreadId)
    '//错误信息//
    If uThread.Handle = lNull Then MsgBox"线程创建错误!"
    End Sub
    '//在类中加入得到Enabled状态属性//
    Public Property Get Enabled()As Boolean
    On Error Resume Next
    Enabled = uThread.Enabled
    End Property
    '//在类中加入Enabled状态设置属性//
    Pubic Property Let Enabled(ByVal vNewValue As Boolean)
    On Error Resume Next
    If vNewValue And (Not uThread.Enabled) Then
       ResumeThread uThread.Handle
       uThread.Enabled = True
    Elself uThread.Enabled Then
       SuspendThread uThread.Handle
       uThread.Enabled=False
    End If
    End Property
    '//在类中加入优先级属性//
    Public Property Get Priority()As Long
    On Error Resume Next
    Priority = GetThreadPriority(uThread.Handle)
    End Property
    '//在类中加入优先级设置属性//
    Public Property Let Priority(ByVal vNewValue As Long)
    On Error Resume Next
    If vNewValue = -2 Then
            Call     SetThreadPriority(uThread.Handle,THREAD_PRIORITY_LOWEST)    '//设置优先级为最低//
    Elself vNewValue = -1 Then
            Call     SetThreadPriority(uThread.Handle,THREAD_PRIORITY_BELOW_NORMAL)    '//设置优先级为最低//
    Elself vNewValue = 0 Then
            CaI1     SetThreadPriority(uThread.Handle,THREAD_PRIORITY_NORMAL)    '//设置优先级为一般//
    Elself vNewValue = 1 Then
            CaI1     SetThreadPriority(uThread.Handle,THREAD_PRIORITY_ABOVE_NORMAL)    '//设置优先级为次高级//
    Elself vNewValue = 2 Then
            CaI1     SetThreadPriority(uThread.Handle,THREAD_PRIORITY_HIGHEST)    '//设置优先级为最高级//
    End If
    End Property
    '//销毁线程(析构函数)
    private Sub Class_Terminate()
    On Error Resume Next
    Call        ThrminateThread(uThread.Handle,0)
    End Sub
    在Form1中调用多线程函数(或过程)的地方添加以下代码(假设有两个需要使用新线程的函数分别为
Function1,Function2):
    Dim Function1 as New NewThreads, Function2 as New NewThreads
    On Error Resume Next
    With Function1
    ·Initialize AddressOf FlickerTop
    ·Enabled = True
    End With
    With Function2
    ·Initialize AddressOf FlickerBottom
    ·Enabled = True
    End With
    在函数实效的地方添加以下代码:
    Set Function1 = Nothing
    Set Function2 = Nothing
    这样,我们在执行程序的时候,实际上就对于Functionl和Function2实现了多线程处理。值得注意的是,
多线程的使用并不能不分情况地滥用,要知道我们在使用多线程的时候,操作系统需要为线程之间的调度增加额外的开销,如果使用不当,应用程序的执行速度不仅得不到提高反而会下降,而且在使用多线程的时候,对于程序的容错性一定要考虑周到,否则多线程的使用会大大增加系统死锁的几率。