多任务和多线程windows 程序设计

上传人:ji****72 文档编号:37695897 上传时间:2018-04-21 格式:DOC 页数:61 大小:333.50KB
返回 下载 相关 举报
多任务和多线程windows 程序设计_第1页
第1页 / 共61页
多任务和多线程windows 程序设计_第2页
第2页 / 共61页
多任务和多线程windows 程序设计_第3页
第3页 / 共61页
多任务和多线程windows 程序设计_第4页
第4页 / 共61页
多任务和多线程windows 程序设计_第5页
第5页 / 共61页
点击查看更多>>
资源描述

《多任务和多线程windows 程序设计》由会员分享,可在线阅读,更多相关《多任务和多线程windows 程序设计(61页珍藏版)》请在金锄头文库上搜索。

1、多任务和多线程多任务和多线程多任务是一个操作系统可以同时执行多个程序的能力。基本上,操作系统使用一个硬件时 钟为同时执行的每个程序配置时间片段 。如果时间片段够小,并且机器也没有由于太多 的程序而超出负荷时,那么在使用者看来,所有的这些程序似乎在同时执行着。 多任务并不是什么新的东西。在大型计算机上,多任务是必然的。这些大型主机通常有几 十甚至几百个终端机和它连结,而每个终端机使用者都应该感觉到他或者她独占了整个计 算机。另外,大型主机的操作系统通常允许使用者提交工作到背景 ,这些背景作业可以 在使用者进行其它工作时,由机器执行完成。 个人计算机上的多任务花了更长的时间才普及化。但是现在 PC

2、 多任务也被认为是很正常 的了。我马上就会讨论到,Microsoft Windows 的16位版本支持有限度的多任务,Windows 的32位版本支持真正的多任务,而且,还多了一种额外的优点,多线程。 多线程是在一个程序内部实作多任务的能力。程序可以把它自己分隔为各自独立的线程 , 这些线程似乎也同时在执行着。这一概念初看起来似乎没有什么用处,但是它可以让程序 使用多执行绪在背景执行冗长作业,从而让使用者不必长时间地无法使用其计算机进行其 它工作(有时这也许不是人们所希望的,不过这种时候去冲冲凉或者到冰箱去看看总是很 不错的)!但是,即使在计算机繁忙的时候,使用者也应该能够使用它。 多任务的各

3、种模式多任务的各种模式在 PC 的早期,有人曾经提倡未来应该朝多任务的方向前进,但是大多数的人还是很迷惑: 在一个单使用者的个人计算机上,多任务有什么用呢?好了,最后事实表示即使是不知道 这一概念的使用者也都需要多任务的。 DOS 下的多任务下的多任务在最初 PC 上的 Intel 8088微处理器并不是为多任务而设计的。部分原因(我在 上一章中 讨论过)是内存管理不够强。当启动和结束多个程序时,多任务的操作系统通常需要移动 内存块以收集空闲内存。在8088上是不可能透明于应用系统来做到这一点的。 DOS 本身对多任务没有太大的帮助,它的设计目的是尽可能小巧,并且与独立于应用程序 之外,因此,

4、除了加载程序以及对程序提供文件系统的存取功能,它几乎没有提供任何支 持。 不过,有创意的程序写作者仍然在 DOS 的早期就找到了一种克服这些缺陷的方法,大多数 是使用常驻(TSR:terminate-and-stay-resident)程序。有些 TSR,比如背景打印队列程序 等,透过拦截硬件时钟中断来执行真正的背景处理。其它的 TSR,诸如 SideKick 等弹出式 工具,可以执行某种型态的工作切换暂停目前的应用程序,执行弹出式工具。DOS 也逐 渐有所增强以便提供对 TSR 的支持。 一些软件厂商试图在 DOS 之上架构出工作切换或者多任务的外壳程序(shell) (诸如 Quarter

5、deck 的 DesqView) ,但是在这些环境中,仅有其中一个占据了大部分市场,当然, 这就是 Windows。 非优先权式的多任务非优先权式的多任务当 Microsoft 在1985年发表 Windows 1.0时,它是最成熟的解决方案,目的是突破 DOS 的局 限。Windows 在实际模式下执行。但是即使这样,它已可以在物理内存中移动内存块。这 是多任务的前提,虽然移动的方法尚未完全透明于应用程序,但是几乎可以忍受了。 在图形窗口环境中,多任务比在一种命令列单使用者操作系统中显得更有意义。例如,在传统的命令列 UNIX 中,可以在命令列之外执行程序,让它们在背景执行。然而,程序的 所

6、有显示输出必须被重新转向到一个文件中,否则输出将和使用者正在做的事情混在一起。窗口环境允许多个程序在相同屏幕上一起执行,前后切换非常容易,并且还可以快速地将 数据从一个程序移动到另一个程序中。例如,将绘图程序中建立的图片嵌入由文书处理程 序编辑的文本文件中。在 Windows 中,以多种方式支持数据转移,首先是使用剪贴簿,后 来又使用动态数据交换(DDE) ,而现在则是透过对象连结和嵌入(OLE) 。 不过,早期 Windows 的多任务实作还不是多使用者操作系统中传统的优先权式的分时多任 务。这些操作系统使用系统时钟周期性地中断一个工作并开始另一个工作。Windows 的这 些16位版本支持

7、一种被称为非优先权式的多任务 ,由于 Windows 消息驱动的架构而使 这种型态的多任务成为可能。通常情况下,一个 Windows 程序将在内存中睡眠,直到它收 到一个消息为止。这些消息通常是使用者的键盘或鼠标输入的直接或间接结果。当处理完 消息之后,程序将控制权返回给 Windows。 Windows 的16位版本不会绝对地依据一个 timer tick 将控制权从一个 Windows 程序切换到 另一个,任何的工作切换都发生在当程序完成对消息的处理后将控制权返回给 Windows 时。 这种非优先权式的多任务也被称为合作式的多任务 ,因为它要求来自应用程序方面的一 些合作。一个 Wind

8、ows 程序可以占用整个系统,如果它要花很长一段时间来处理消息的话。虽然非优先权式的多任务是16位 Windows 的一般规则,但仍然出现了某些形式的优先权式 多任务。Windows 使用优先权式多任务来执行 DOS 程序,而且,为了实作多媒体,还允 许动态链接库接收硬件时钟中断。 16位 Windows 包括几个功能特性来帮助程序写作者解决(或者,至少可以说是对付)非优 先权式多任务中的局限,最显著的当然是时钟式鼠标光标。当然,这并非一种解决方案, 而仅仅是让使用者知道一个程序正在忙于处理一件冗长作业,因而让使用者在一段时间内 无法使用系统。另一种解决方案是 Windows 定时器,它允许程

9、序周期性地接收消息并完成 一些工作。定时器通常用于时钟应用和动画。 针对非优先权式多任务的另一种解决方案是 PeekMessage 函数呼叫,我们曾在第五章中的 RANDRECT 程序里看到过。一个程序通常使用 GetMessage 呼叫从它的消息队列中找寻下 一个消息,不过,如果在消息队列中没有消息,那么 GetMessage 不会传回,一直到出现一 个消息为止。而另一方面,PeekMessage 将控制权传回程序,即使没有等待的消息。这样, 一个程序可以执行一个冗长作业,并在程序代码中混入 PeekMessage 呼叫。只要没有这个 程序或其它任何程序的消息要处理,那么这个冗长作业将继续执

10、行。 Presentation Manager 和序列化的消息队列和序列化的消息队列Microsoft 在一种半 DOS/半 Windows 的环境下实作多任务的第一个尝试(和 IBM 合作)是 OS/2和 Presentation Manager(缩写成 PM )。虽然 OS/2明确地支持优先权式多任务,但是 这种多任务方式似乎并未在 Presentation Manager 中得以落实。问题在于 PM 序列化来自键 盘和鼠标的使用者输入消息。这意味着,在前一个使用者输入消息被完全处理以前,PM 不会将一个键盘或者鼠标消息传送给程序。 尽管键盘和鼠标消息只是一个 PM(或者 Windows)

11、程序可以接收的许多消息中的几个, 大多数的其它消息都是键盘或者鼠标事件的结果。例如,菜单命令消息是使用者使用键盘 或者鼠标进行菜单选择的结果。在处理菜单命令消息时,键盘或者鼠标消息并未完全被处 理。 序列化消息队列的主要原因是允许使用者的预先键入键盘按键和预先按入鼠标按钮。如果一个键盘或者鼠标消息导致输入焦点从一个窗口切换到另一个窗口,那么接下来 的键盘消息应该进入拥有新的输入焦点的窗口中去。因此,系统不知道将下一个使用者输 入消息发送到何处,直到前一个消息被处理完为止。 目前的共识是不应该让一个应用系统有可能占用整个系统,而这需要非序列化的消息队列, 32位版本的 Windows 支持这种消

12、息队列。如果一个程序正在忙着处理一项冗长作业,那么 您可以将输入焦点切换到另一个程序中。 多线程解决方案多线程解决方案我讨论 OS/2的 Presentation Manager,只是因为它是第一个为早期的 Windows 程序写作者 (比如我自己)介绍多线程的环境。有趣的是,PM 实作多线程的局限为程序写作者提供 了应该如何架构多线程程序的必要线索。即使这些限制在32位的 Windows 中已经大幅减少, 但是从更有限的环境中学到的经验仍然是非常有效的。因此,让我们继续讨论下去。 在一个多线程环境中,程序可以将它们自己分隔为同时执行的片段(叫做执行绪) 。对执行 绪的支持是解决 PM 中存在

13、的序列化消息队列的最好方法,并且在 Windows 中线程有更实 际的意义。 就程序代码来说,一个线程简单地被表示为可能呼叫程序中其它函数的函数。程序从其主 线程开始执行,这个主执行绪是在传统的 C 程序中叫做 main 的函数,而在 Windows 中是 WinMain。一旦执行起来,程序可以通过在系统呼叫 CreateThread 中指定初始线程函数的 名称来建立新的线程的执行。操作系统在执行绪之间优先权式地切换控件,和它在程序之 间切换控制权的方法非常类似。 在 OS/2的 Presentation Manager 中,每个线程可以建立一个消息队列,也可以不建立。如 果希望从线程建立窗口

14、,那么一个 PM 线程必须建立消息队列。否则,如果只是进行许多 的数据处理或者图形输出,那么线程不需要建立消息队列。因为无消息队列的程序不处理 消息,所以它们将不会当住系统。唯一的限制是一个无消息队列线程无法向一个消息队列 线程中的窗口发送消息,或者呼叫任何发送消息的函数(不过,它们可以将消息递送给消 息队列线程) 。 这样,PM 程序写作者学会了如何将它们的程序分隔为一个消息队列线程(在其中建立所 有的窗口并处理传送给窗口的消息)和一个或者多个无消息队列线程,在其中执行冗长的 背景工作。PM 程序写作者还了解到1/10秒规则 ,大体上,程序写作者被告知,一个消 息队列线程处理任何消息都不应该

15、超过1/10秒,任何花费更长时间的事情都应该在另一个 线程中完成。如果所有的程序写作者都遵循这一规则,那么将没有 PM 程序会将系统当住 超过1/10秒。 多线程架构多线程架构我已经说过 PM 的限制让程序写作者理解如何在图形环境中执行的程序里头使用多个执行 绪提供了必要的线索。因此在这里我将为您的程序建议一种架构:您的主执行绪建立您程 序所需要的所有窗口,并在其中包含所有的窗口消息处理程序,以便处理这些窗口的所有 消息;所有其它执行绪只进行一些背景处理,除了和主执行绪通讯,它们不和使用者进行 交流。 可以把这种架构想象成:主线程处理使用者输入(和其它消息) ,并建立程序中的其它线程, 这些附

16、加的线程完成与使用者无关的工作。 换句话说,您程序的主线程是一个老板,而您的其它线程是老板的职员。老板将大的工作 丢给职员处理,而他自己保持和外界的联系。因为那些线程仅仅是职员,所以其它线程不 会举行它们自己的记者招待会。它们会认真地完成自己的工作,将结果报告给老板,并等待他们的下一个任务。 一个程序中的线程是同一程序的不同部分,因此他们共享程序的资源,如内存和打开的文 件。因为线程共享程序的内存,所以他们还共享静态变量。然而,每个线程都有他们自己 的堆栈,因此动态变量对每个线程是唯一的。每个线程还有各自的处理器状态(和数学协 处理器状态) ,这个状态在进行线程切换期间被储存和恢复。 线程间的线程间的争吵争吵正确地设计、写作和测试一个复杂的多线程应用程序显然是 Windows 程序写作者可能遇到 的最困难的工作之一。因为优先权式多任务系统可以在任何时刻中断一个线程,并将控制 权切换到另一个线程中,在两个线程之间可能有无法预料的随机交互作用的情况。 多线程程序中的一个常见的错误被称为竞争状态(race condition) ,这发生在程序写

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号