0 引言
在多种可视化编程语言中,VB 具有界面设计功
能强的特点 ,选择它作为开发平台 ,可以快速地创建
应用程序。该特点使其在测控系统的数据采集和处
理中应用比较广泛 ,但是在数据实时处理时 ,往往出
现执行操作界面的菜单命令明显反应变慢 ,操作不
便 ,实时监控数据时引发了程序阻塞。导致此问题
的原因是仅通过一个任务体系解决大数据量的实时
传输与处理 ,而应用多线程的编程思想 ,把实时数据
的采集与界面的操作通过不同的线程来完成 ,就会
解决此问题。然而 ,用 VB 开发多线程的实时数据
采集与处理系统有一定的难度。笔者系统地论述了
VB 的多线程设计 ,建立了相应的算法 ,结合数控压
力校验系统 ,给出了设计的流程 ,并通过实例说明多
线程算法的可行性。
1 进程与线程
Windows 操作系统既支持多进程 ,又支持多线
程。进程是应用程序的一次执行 ,每个进程是由私有的虚拟地址空间、代码、数据和其他系统资源组成
的。而线程是比进程更小的能独立运行的基本单
位 ,是进程的执行路径 ,它包含独立的堆栈和 CPU
寄存器状态 ,每个线程是进程内部的可执行路径 ,是
进程的执行单元。从根本上说 ,线程是可由系统调
度的最简单代码单元 ,负责执行包含在进程的地址
空间中的程序代码。一个进程一般都要有一个线
程 ,叫做主线程 ,进程也可以包括多个线程 ,所有属
于该进程的线程都共享进程的资源 ,如 CPU、地址空
间以及对象句柄等。
在多线程程序中 ,每一个线程都有自己的堆栈 ,
并独立于应用程序内的其他线程而运行 ,多个线程
可以同时运行。利用多线程机制可以实现进程内的
各个子任务并行执行 ,从而提高系统的实时性能。
把实时数据的读取与处理数据的界面操作交给不同
的两个线程并发执行 ,即可解决上面提到的问题。
多线程模式的工作原理和编程机制对于 VB 并
不完全适合 ,在VB 中较少涉及到多线程的问题 ,这
是因为VB 并不具备线程安全性。通过 VB 实现多
线程应用程序时 ,应用程序必须满足放弃用户交互 ,
即不能有类似于窗口之类的用户界面。因此不能用
VB 的串口通信控件 MSComm 来进行实时数据的采
集 ,可以通过动态链接库 DLL 的函数调用实现串行
通信。
与VB 相比较 ,VC 的MFC 库支持 Windows 所提
供的辅助线程和用户界面线程 ,用户界面线程通常
有窗口 ,因此它具有自己的消息循环 ,这是 VB 所不
能及的。关于线程间通信 ,VB 和VC 都可以通过全
局变量实现 ,但 VC 还可以利用线程同步技术来实
现。相比之下 ,VC 的多线程机制要比 VB 安全 ,功
能也强大。
2 VB 多线程的设计
VB 多线程的创建需要在通用模块中声明
Win32API 动态链接库 ,而此动态链接库具有创建线
程的函数 ,创建线程的流程图如图1 所示。
图1 创建线程
根据线程函数的地址定义线程体名 ,关于此线
程体的应用代码加入到公用模块中 ,由创建线程到
停止线程的流程如图2 所示。
3 某压力校验系统实时数据采集与处理
线程的设计
压力指示表、压力变送器和压力开关是工业上
图2 实时数据采集与
处理线程工作流程
使用最为广泛的仪表 ,工
业生产很多都是高温高压
的过程 ,且很多设备处于
极限运行状态。因此压力
仪表的稳定性和准确性就
显得尤为重要。此数控压
力校验系统按照无纸化管
理和网络共享来实现集压
力测量、压力仪表校验、误
差自动处理、校验表格和
证书自动生成、历史数据自动存储和可分类查询的
标准校验系统。
311 创建实时数据采集与处理的线程算法
在通用模块中声明创建线程的函数:
Public Declare Function Create Thread Lib″ker2
nel32″(ByVal 1pThreadAttributes As long , By Val dw2
StackSize As Long ,ByVal 1pStartAddress As Long ,ByVal
1pParameter As Any , ByVal dwCreationFlags As Long ,
1pThreadId As Long) As Long
参数含义:
1pThreadAttributes 如果传递 NULL ,该线程使用
默认安全属性。如果希望所有的子进程能够继承该
线程对象的句柄 ,必须将它的 bInheritHandle 成员被
初始化为 TRUE。
dwStackSize 设定线程堆栈的地址空间。如果非
0 ,函数将所有的存储器保留并分配给线程的堆栈。
如果是 0 ,Create Thread 就保留一个区域 ,并且将链
接程序嵌入. exe 文件的/ STACK 链接程序 ,开关信
息指明的存储器容量分配给线程堆栈。
1pStartAddress 线程函数的地址。
1pParameter 传递给线程函数的参数。
dwCreationFlags 如果是 0 ,线程创建后立即进行
调度。如果是 CREATE- SUSPENDED ,系统对它进行
初始化后暂停该线程的运行。
lpThreadId 用来存放系统分配给新线程的 ID。
接下来再声明两个 API 函数 ,是用来退出线程
的。
Public Declare Sub ExitThread Lib″kernel32″(ByVal
hThread As Long ,1pExitCode As Long) As Long
Public Declare Function GetExitCodeThread Lib″ker2
nel32″(ByVal dwExitCode As Long)
定义两个变量 ,变量 hThread 是线程的句柄。
Dim hThread As Long ,idThread As Long
创建线程的代码如下:
Public Sub StartThread (ByVal i As Long)
idThread = 0
hThread = CreateThread ( 0 &, 0 &, AddressOf
thread1proc ,i &,0 &,idThread)
If hThread = 0 Then MsgBox″创建线程失败″
End Sub
停止线程的代码如下:
Public Function Stop Thread () As Long
Do
Call GetExitCodeThread (hThread ,StopThread)
DoEvents
Loop While StopThread = STILL - ACTIVE
CloseHandle hThread
hThread = 0
End Function
在创建线程的代码中用了AddressOf 语法 ,所创
建的 线 程 从 thread1proc 处 开 始 , 线 程 体 名 是
thread1proc ,在公用模块中加入应用代码;
Public Function thread1proc () As Long
在此加入实时数据采集和处理的应用代码End Function
在调试运行的时候应该注意 , 在编译环境和
EXE 模式下效果会不同 ,在编译模式下容易非法操
作。还有在线程中 ,不能用 DoEvents ,可以多次调用
StartThread 来达到多线程 ,局部变量各自独立。
312 实时数据采集与处理的实现
选择四零四科技公司所出品的 Pcomm Pro 软件
中的通信用动态链接库的DLL 文件 Pcomm. dll 进行
串口通信。首先要进行声明 ,所声明的函数包括通
信端口的打开( sio - open) / 关闭( sio - close) 、传输参
数设置(sio - ioct1) 及硬件线路控制(sio - DTR) 等。
在VB 环境下使用 Pcomm Pro 函数库先要引入函
数声明,让程序知道函数所在的位置。此通信函数库
已经预先准备了常用的模块,只要引入到所创建的工
程中即可。该程序用到的模块是 Pcomm. bas (常数定
义及函数声明模块) ,当函数库安装后,这个模块就存
在于计算机中,将其复制到工程目录中,在工程使用
中加入模块功能即可。部分重要的代码如下:
· 打开 COM1 端口
Public Sub COMOpen ()
Call sio - open (1)
Call sio - ioct1 (1 ,B9600 ,BIT- 8)
End Sub
· 读端口数据
Public Function COMRead () As Boolean
Dim TT&
Dim result As Long
Dim ReceiveData (5) As Byte
On Error Resume Next
TT = GetTickCount ()
R0 :result = sio - read (1 ,ReceiveData (0) ,1)
If result = 0 Then
If GetTickCount () - TT < = 1000 Then Go To
R0
End if
⋯⋯Eng Function
· 处理读取数据并根据运行方式输出:
db1H = ReceiveData (3) ’高字节
db1L = ReceiveData (4) ’低字节
ReadData = db1H 3 256 + db1L
在程序设计时 ,要注意上位机与压力表之间的
通讯协议。其中波特率:9 600 bit/ s ;数据格式:1 位
起始位 ,8 位数据位 ,无校验位 ,一位停止位;校验和
算法:校验和 = 所发数求和除以 256 取余。界面菜
单的操作放在主线程中 ,实现压力仪表校验、误差自
动处理、校验表格和证书自动生成、历史数据自动存
储和可分类查询等功能。
4 结论
通过在进程中创建一个新的线程实现实时数据
采集与处理,即构成独立的分支 ,完善了 VB 多线程
处理任务的功能 ,在很大程度上简化了程序的复杂
性 ,使VB 高效、快速以及强大的界面设计功能最大
程度上得到了应用。