专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Windows » 多线程编程:Windows95下多线程编程技术及其实现 »正文

多线程编程:Windows95下多线程编程技术及其实现

来源: 发布时间:星期二, 2008年12月30日 浏览:2次 评论:0
笔者最近在开发基于Internet网上可视电话过程中碰到了这样个问题,即在基于In ternet网上可视电话系统中,同时要进行语音采集、语音编译码、图像采集、图像编译码、语音和图像码流传输,所有这些工作,都要并行处理特别是语音信号,如果进行图像编解码时间过长,语音信号得不到服务,通话就有间断;如果图像或语音处理时间过长,而不能及时传输码流数据,通信同样也会中断这样就要求我们实现种并行编程,在只有个CPU机器上,也就是要将该CPU时间按时优先准则分配给各个事件,定期处理各事件,而不会对某事件处理过长在32位Windows95或Windows NT下,我们可以用多线程处理技术来实现这种并行处理实际上,这种并行编程在很多场合下都是必须例如,在File Manager拷贝文件时,它显示个对话框中包含了个Cancel按钮如果在文件拷贝过程中,点中Cance l按钮,就会终止拷贝在16位Winows中,实现这类功能需要在File Copy循环内部周期性地PeekMessage如果正在读个很大动作;如果从软盘读文件,则要花费好几秒时间由于机器反应太迟钝,用户会频繁地点中这个按钮,以为系统不知道想终止这个操作如果把File Copy指令放入另外个线程,就不需要在代码中放大堆PeekMessage,处理用户界面线程将和它分开操作,点中Cancel按钮后会立即得到响应同样道理,在应用中创建个单独线程来处理所有打印任务也是很有用,用户可以在打印处理时继续使用应用

线程概念

为了了解线程概念 ,我们必须先讨论下进程概念个进程通常定义为个例子在32位Windows中,进程占据4GB虚拟地址空间和它们在MS-DOS和16位Windows操作系统中区别,32位Windows进程是没有活力这就是说,个32位Windows进程并不执行什么指令,它只是占据着4GB地址空间,此空间中有应用EXE文件代码和数据

EXE需要DLL也将它们代码数据装入到进程地址空间除了地址空间,进程还占有某些资源,比如文件、动态内存分配和线程当进程终止时,在它生命期中创建各种资源将被清除

如上所述,进程是没有活力,它只是个静态概念为了让进程完成些工作,进程必须至少占有线程,所以线程是描述进程内执行,正是线程负责执行包含在进程地址空间中代码实际上,单个进程可能包含几个线程,它们可以同时执行进程地址空间中代码为了做到这点,每个线程有自己组CPU寄存器和椎每个进程至少有个线址程在执行其地址空间中代码,如果没有线程执行进程地空间中代码,如果没有线程执行进程地址空间中代码,进程也就没有继续存在理由,系统将自动清除进程及其地址空间为了运行所有这些线程,操作系统为每个独立线程安排些CPU时间,操作系统以轮转方式向线程提供时间片,这就给人种假象,好象这些线程都在同时运行创建个32位Windows进程时,它个线程称为主线程,由系统自动生成,然后可由这个主线程生成额外线程,这些线程又可生成更多线程

线程编程技术

1.编写线程

所有线程必须从个指定开始执行,该称为线程,它必须具有下列原型: DWORD WINAPI YourThreadFunc(LPVOID lpvT.hreadParm);

输入个LPVOID型参数,可以是个DWORD型整数,也可以是个指向个缓冲区指针,返回个DWORD型像WinMain样,这个并不由操作系统,操作系统包含在KERNEL32.DLL中非C运行时个内部,如StartOfThread,然后由S tartOfThread建立起个异常处理框架后,我们

2.创建个线程

个进程主线程是由操作系统自动生成,如果要让个主线程创建额外线程,可以CreateThread来完成格式如下:

HANDLE CreateThread(LPSECURITY_ATTRIBUTES jpsa.DWORD cbstack,LPTHREAD_START _ROUTINE lpStartAddr.LPVOID lpvThreadParm,DWORD fdwCreate,LPDWORD lpIDThread);

其中参数意义如下:

lpsa:是个指向SECURITY_ATTRIBUTES结构指针如果想让对象为缺省安全属性话,可以传个NULL;如果想让任个子进程都可继承该线程对象句柄,必须指定个SECURITY _ATTRIBUTES结构,其中bInheritHandle成员化为TURE

cbstark:表示线程为自己所用堆栈分配地址空间大小,0表示采用系统缺省值

lpStartAddr:表示新线程开始执行时代码所在地址,即为线程

lpvThreadParm:是传入线程参数

fdwCreate:指定控制线程创建附加标志,可以取两种值如果该参数为0,线程就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,化CPU,登记CONTEXT结构成员,准备好执行该线程条指令,但并不马上执行,而是挂起该线程

lpIDThrdad:是个DWORD类型地址,返回赋给该新线程ID值

3.终止线程

如果某线程了ExitThread,就可以终止自己,如:

VOID ExtThead(UNIT fuExitCode);

这个线程设置了退出码fuExitCode后,就终止该线程

TerminateThread亦可终止线程如:

BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);

用来结束由hThread参数指定线程,并把dwExitCode设成该线程退出码

当某个线程不再响应时,我们可以用其他线程来终卡这个不响应线程

4.设定线程相对优先级

个线程被首次创建时,它优先级等同于它所属进程优先级在单个进程内可以通过SetThreadPrionrity改变线程相对优先级个线程优先级是相对于其所属进程优先级而言

BOOL SetThreadPriority(HANDLE hThread,nPriority);

其中参数hThread是指向待修改优先级线程句柄,nPriority可以是以下值:


THREAD_PRIORITY_LOWEST

THREAD_PRIORITY_BELOW_NORMAL

THREAD_PRIORITY_NORMAL

THREAD_PRIONRITY_ABOVE_NORMAL

THREAD_PRIONITY_HIGHEST

5.挂起及恢复线程
前文提到过可以创建挂起状态线程,可以通过传递(CREATE_SUSPENDED标志给Cre ated来实现当这样操作时,系统创建指定线程核心对象,创建线程栈,在CONTEXT结构中化线程CPU注册成员然而,线程对象被分配了挂起计数值1,这表明系统将不再分配CPU去执行线程要开始执行个线程,另个线程必须ResumeThread并传递给它CreateThread时返回线程句柄格式如下:

DWORD ResumeThread(HANDLE hThread);

个线程可以被挂起多次如果个线程被挂起3次,则该线程在它被分配CPU的前必须被恢复3次除了在创建线程时使用CREATE_SUSPENDED标志,还可以用SuspendThread挂起线程格式如下:

DWORD SuspendThread(HANDLE hThread)

多线程编程技术应用

如前所述,为了实现基于TCP/IP下可视电话,就必须"并行"地执行语音采集、语音编解码、图像采集、图像编解以及码流数据接收和发送语音和图像采集由硬件采集卡进行,我们只需化该硬件采集卡,然后实时读取采集数据即可,但语音和图像数据编解码以及码流数据传输都必须由去协调执行,让CPU轮流为各个事件服务,决不能在某件事件上处理过长Windows 95下线程正是满足这种要求编程技术

本文给出了利用Windows 95环境下用多线程编程技术实现基于TCP/IP可视电话部分源码,其中包括主窗口过程以及主叫端和被叫端TCP/IP接收线程和语音编解码线程由于图像编解码实时性比语音处理和传输模块实时性要求要低些,所以以语音编解码为事件去查图像数据,然后进行图像编解码,而没有为图像编解码去单独实现个线程

在主窗口化时,用CREATE_SUSPENDED标志创建了两个线程hThreadG7231和hThreadT CPRev个用于语音编解码,它线程为G723Proc,该线程不断查询本地有无编好码语音和图像码流,如有,则进行H.223打包,然后通过TCP端口发送给对方另外个线程用于TCP/IP接收,它线程为AcceptThreadProcRiv,该线程不断侦测TCP/IP端口有无对方传来码流,如有,就接收码流,进行H.223解码后送入相应缓冲区该缓冲区内容, 由语音编解码线程G723Proc查询,并送入相应解码器,由于使用了多线程编程技术,使得操作系统定时去服务语音编解码模块和传输模块,从而保证了通信不中断 

相关文章

读者评论

  • 共0条 分0页

发表评论

  • 昵称:
  • 内容: