深入浅出WindowsAPI程序设计:核心编程篇全文免费阅读

简介: 本书基于win 10和VS 2019编写,系统地介绍了Windows程序设计的核心编程思想与实践。

第1章

多线程编程

磁盘中存储的可执行文件是由指令和数据等组成的二进制文件,是一个静态的概念。进程(process)是系统中正在运行的一个可执行文件,可执行文件一旦运行就成为进程,是一个动态的概念,是一个活动的实体。进程是一个正在运行的可执行文件所使用的资源的总和,包括虚拟地址空间、代码、数据、对象句柄、环境变量等。一个可执行文件被同时多次执行,产生多个进程,虽然它们是同一个可执行文件,但是它们的虚拟地址空间是相互隔离的,就像不同的可执行文件在同时执行。

进程是不“活泼”的。要使进程中的代码被真正运行,必须拥有在这个进程环境中运行代码的“执行单元”,也就是线程。线程是操作系统分配CPU处理器时间的基本单位,一个线程可以看作一个执行单元,它负责执行进程地址空间中的代码。当一个进程被创建时,系统会自动为它创建一个线程。这个线程从程序指定的入口地址处开始执行,通常把这个线程称为主线程。当主线程执行完最后一行代码(例如return msg.wParam;)时,进程结束,这时系统会撤销进程所拥有的地址空间和资源,程序终止。

在主线程中,程序可以继续创建多个线程来“同时”执行进程地址空间中的代码,这些线程被称为子线程。操作系统为每个线程保存各自的寄存器和栈环境,但是它们共享进程的地址空间、对象句柄、代码和数据等其他资源,它们可以执行相同的代码,可以对相同的数据进行操作,也可以使用相同的句柄。进程和线程的关系可以看作“容器”和“内容物”的关系,进程是线程的容器,线程总是在某个进程的环境中被创建,它不可以脱离进程而单独存在,而且线程的整个生命周期都存在于进程中,如果进程被终止,则其中的线程也会同时结束。

系统中可以同时存在多个进程,每个进程中又可以有多个线程同时执行。为了使所有进程中的线程都能够“同时”执行,操作系统为每个线程轮流分配CPU时间片。当轮到一个线程执行的时候,系统将保存的线程的寄存器值恢复并开始执行。当时间片结束时,系统将线程当前的寄存器环境保存下来并切换到另一个线程中执行,如此循环。

对单CPU处理器的计算机来说,不同线程实际上是在轮流使用同一个处理器。一个程序的运行速度并不会因为创建了多个线程而加快,因为线程多了以后,每个线程等待时间片的时间也就越长。但是对于多核CPU的计算机,操作系统可以将不同的线程安排到不同的处理器内核中执行,系统可以同时执行与计算机上的CPU处理器内核一样多的线程,这样一个进程中的多个线程会因为同时获得多个时间片而加快整个进程的运行速度。

不过,多线程编程的出发点并不仅仅是为了充分利用多核CPU,编程过程中会遇到仅依靠一个主线程无法解决问题的情况,下面我们将通过一个典型的“问题程序”来引出多线程编程。

1.1

使用多线程的必要性

本节的示例程序界面如图1.1所示。

图1.1

初始状态下,停止、暂停和继续按钮是禁用的,用户单击“开始”按钮,调用自定义函数Counter进入一个while循环。在循环中,不停地把一个数进行自加,并实时显示到编辑控件中。在计数循环过程中,用户可以随时按下“停止”“暂停”或“继续”按钮。

Counter.cpp源文件的内容如下:

#include <windows.h>#include "resource.h"#pragma comment(linker,"\"/manifestdependency:type='win32' \ name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")// 常量定义#define F_START 1 // 开始计数#define F_STOP 2 // 停止计数// 全局变量HWND g_hwndDlg;int g_nOption; // 标志// 函数声明INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);VOID Counter();int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ // 创建模态对话框 DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, NULL); return 0;}INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){ static HWND hwndBtnStart, hwndBtnStop, hwndBtnPause, hwndBtnContinue;

版权:人民邮电出版社