2022年多线程编程基础 .pdf
《2022年多线程编程基础 .pdf》由会员分享,可在线阅读,更多相关《2022年多线程编程基础 .pdf(35页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、多 线 程 编 程 之 一 问 题 提 出作 者 : 韩 耀 旭一 、 问 题 的 提 出编 写 一 个 耗 时 的 单 线 程 程 序 :新 建 一 个 基 于 对 话 框 的 应 用 程 序 SingleThread, 在 主 对 话 框IDD_SINGLETHREAD_DIALOG添 加 一 个 按 钮 , ID 为 IDC_SLEEP_SIX_SECOND,标 题 为 “ 延 时 6 秒 ” , 添 加 按 钮 的 响 应 函 数 , 代 码 如 下 :void CSingleThreadDlg:OnSleepSixSecond() Sleep(6000); /延时 6 秒 编 译 并
2、 运 行 应 用 程 序 ,单 击 “ 延 时 6 秒 ” 按 钮 ,你 就 会 发 现 在 这 6 秒 期 间 程 序就 象 “ 死 机 ” 一 样 ,不 在 响 应 其 它 消 息 。为 了 更 好 地 处 理 这 种 耗 时 的 操 作 ,我 们 有必 要 学 习 多 线 程 编 程 。二 、 多 线 程 概 述进 程 和 线 程 都 是 操 作 系 统 的 概 念 。进 程 是 应 用 程 序 的 执 行 实 例 ,每 个 进 程 是由 私 有 的 虚 拟 地 址 空 间 、代 码 、数 据 和 其 它 各 种 系 统 资 源 组 成 ,进 程 在 运 行 过 程中 创 建 的 资 源
3、 随 着 进 程 的 终 止 而 被 销 毁 , 所 使 用 的 系 统 资 源 在 进 程 终 止 时 被 释 放或 关 闭 。线 程 是 进 程 内 部 的 一 个 执 行 单 元 。系 统 创 建 好 进 程 后 ,实 际 上 就 启 动 执 行 了该 进 程 的 主 执 行 线 程 ,主 执 行 线 程 以 函 数 地 址 形 式 ,比 如 说 main或 WinMain函数 , 将 程 序 的 启 动 点 提 供 给 Windows系 统 。 主 执 行 线 程 终 止 了 , 进 程 也 就 随 之终 止 。每 一 个 进 程 至 少 有 一 个 主 执 行 线 程 ,它 无 需
4、由 用 户 去 主 动 创 建 ,是 由 系 统 自动 创 建 的 。用 户 根 据 需 要 在 应 用 程 序 中 创 建 其 它 线 程 ,多 个 线 程 并 发 地 运 行 于 同一 个 进 程 中 。一 个 进 程 中 的 所 有 线 程 都 在 该 进 程 的 虚 拟 地 址 空 间 中 ,共 同 使 用 这些 虚 拟 地 址 空 间 、全 局 变 量 和 系 统 资 源 ,所 以 线 程 间 的 通 讯 非 常 方 便 ,多 线 程 技术 的 应 用 也 较 为 广 泛 。多 线 程 可 以 实 现 并 行 处 理 , 避 免 了 某 项 任 务 长 时 间 占 用 CPU 时 间
5、 。 要 说 明的 一 点 是 ,目 前 大 多 数 的 计 算 机 都 是 单 处 理 器( CPU)的 ,为 了 运 行 所 有 这 些 线程 , 操 作 系 统 为 每 个 独 立 线 程 安 排 一 些 CPU 时 间 , 操 作 系 统 以 轮 换 方 式 向 线 程提 供 时 间 片 ,这 就 给 人 一 种 假 象 ,好 象 这 些 线 程 都 在 同 时 运 行 。由 此 可 见 ,如 果两 个 非 常 活 跃 的 线 程 为 了 抢 夺 对 CPU 的 控 制 权 , 在 线 程 切 换 时 会 消 耗 很 多 的 CPU名师资料总结 - - -精品资料欢迎下载 - - -
6、- - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 35 页 - - - - - - - - - 资 源 , 反 而 会 降 低 系 统 的 性 能 。 这 一 点 在 多 线 程 编 程 时 应 该 注 意 。Win32 SDK函 数 支 持 进 行 多 线 程 的 程 序 设 计 , 并 提 供 了 操 作 系 统 原 理 中 的各 种 同 步 、 互 斥 和 临 界 区 等 操 作 。 Visual C+ 6.0中 , 使 用 MFC 类 库 也 实 现 了多 线 程 的 程 序 设 计 , 使 得 多 线 程 编 程 更
7、 加 方 便 。三 、 Win32 API对 多 线 程 编 程 的 支 持Win32 提 供 了 一 系 列 的 API 函 数 来 完 成 线 程 的 创 建 、 挂 起 、 恢 复 、 终 结 以及 通 信 等 工 作 。 下 面 将 选 取 其 中 的 一 些 重 要 函 数 进 行 说 明 。1、 HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD
8、 dwCreationFlags, LPDWORD lpThreadId); 该 函 数 在 其 调 用 进 程 的 进 程 空 间 里 创 建 一 个 新 的 线 程 , 并 返 回 已 建 线 程 的 句 柄 ,其 中 各 参 数 说 明 如 下 :?lpThreadAttributes:指 向 一 个 SECURITY_ATTRIBUTES 结 构 的 指 针 ,该结 构 决 定 了 线 程 的 安 全 属 性 , 一 般 置 为 NULL ;?dwStackSize: 指 定 了 线 程 的 堆 栈 深 度 , 一 般 都 设 置 为 0;?lpStartAddress: 表 示 新
9、线 程 开 始 执 行 时 代 码 所 在 函 数 的 地 址 , 即 线 程 的起 始 地 址 。 一 般 情 况 为 (LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc 是 线 程 函 数 名 ;?lpParameter:指 定 了 线 程 执 行 时 传 送 给 线 程 的 32 位 参 数 ,即 线 程 函 数 的参 数 ;?dwCreationFlags: 控 制 线 程 创 建 的 附 加 标 志 , 可 以 取 两 种 值 。 如 果 该 参数 为 0, 线 程 在 被 创 建 后 就 会 立 即 开 始 执 行 ; 如 果 该 参 数 为
10、CREATE_SUSPENDED,则 系 统 产 生 线 程 后 , 该 线 程 处 于 挂 起 状 态 , 并 不 马上 执 行 , 直 至 函 数 ResumeThread被 调 用 ;?lpThreadId: 该 参 数 返 回 所 创 建 线 程 的 ID ;如 果 创 建 成 功 则 返 回 线 程 的 句 柄 , 否 则 返 回 NULL 。2、 DWORD SuspendThread(HANDLE hThread); 该 函 数 用 于 挂 起 指 定 的 线 程 , 如 果 函 数 执 行 成 功 , 则 线 程 的 执 行 被 终 止 。3、 DWORD ResumeThre
11、ad(HANDLE hThread); 该 函 数 用 于 结 束 线 程 的 挂 起 状 态 , 执 行 线 程 。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 35 页 - - - - - - - - - 4、 VOID ExitThread(DWORD dwExitCode); 该 函 数 用 于 线 程 终 结 自 身 的 执 行 , 主 要 在 线 程 的 执 行 函 数 中 被 调 用 。 其 中 参 数dwExitCode用 来 设 置 线 程 的 退 出
12、 码 。5、 BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode); 一 般 情 况 下 ,线 程 运 行 结 束 之 后 ,线 程 函 数 正 常 返 回 ,但 是 应 用 程 序 可 以 调用 TerminateThread强 行 终 止 某 一 线 程 的 执 行 。 各 参 数 含 义 如 下 :?hThread: 将 被 终 结 的 线 程 的 句 柄 ;?dwExitCode: 用 于 指 定 线 程 的 退 出 码 。使 用 TerminateThread()终 止 某 个 线 程 的 执 行 是 不 安 全 的 , 可 能
13、会 引 起 系 统不 稳 定 ;虽 然 该 函 数 立 即 终 止 线 程 的 执 行 ,但 并 不 释 放 线 程 所 占 用 的 资 源 。因 此 ,一 般 不 建 议 使 用 该 函 数 。6、 BOOL PostThreadMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam); 该 函 数 将 一 条 消 息 放 入 到 指 定 线 程 的 消 息 队 列 中 , 并 且 不 等 到 消 息 被 该 线 程 处 理时 便 返 回 。?idThread: 将 接 收 消 息 的 线 程 的 ID ;?Msg : 指
14、 定 用 来 发 送 的 消 息 ;?wParam : 同 消 息 有 关 的 字 参 数 ;?lParam : 同 消 息 有 关 的 长 参 数 ;调 用 该 函 数 时 , 如 果 即 将 接 收 消 息 的 线 程 没 有 创 建 消 息 循 环 , 则 该 函 数 执 行 失 败 。四 、 Win32 API多 线 程 编 程 例 程例 程 1 MultiThread1 1.建 立 一 个 基 于 对 话 框 的 工 程 MultiThread1, 在 对 话 框IDD_MULTITHREAD1_DIALOG中 加 入 两 个 按 钮 和 一 个 编 辑 框 , 两 个 按 钮的 I
15、D 分 别 是 IDC_START, IDC_STOP , 标 题 分 别 为 “ 启 动 ” , “ 停 止 ” ,IDC_STOP的 属 性 选 中 Disabled; 编 辑 框 的 ID 为 IDC_TIME , 属 性 选 中Read-only;2.在 MultiThread1Dlg.h文 件 中 添 加 线 程 函 数 声 明 :3.void ThreadFunc(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 35 页 - - - - - - - -
16、- 注 意 , 线 程 函 数 的 声 明 应 在 类CMultiThread1Dlg的 外 部 。在 类CMultiThread1Dlg内 部 添 加 protected型 变 量 :HANDLE hThread; DWORD ThreadID; 分 别 代 表 线 程 的 句 柄 和 ID 。4.在 MultiThread1Dlg.cpp文 件 中 添 加 全 局 变 量 m_bRun :5.volatile BOOL m_bRun; m_bRun 代 表 线 程 是 否 正 在 运 行 。你 要 留 意 到 全 局 变 量 m_bRun 是 使 用 volatile 修 饰 符 的 ,v
17、olatile 修 饰符 的 作 用 是 告 诉 编 译 器 无 需 对 该 变 量 作 任 何 的 优 化 , 即 无 需 将 它 放 到 一 个寄 存 器 中 , 并 且 该 值 可 被 外 部 改 变 。 对 于 多 线 程 引 用 的 全 局 变 量 来 说 ,volatile 是 一 个 非 常 重 要 的 修 饰 符 。编 写 线 程 函 数 :void ThreadFunc() CTime time; CString strTime; m_bRun=TRUE; while(m_bRun) time=CTime:GetCurrentTime(); strTime=time.Form
18、at(%H:%M:%S); :SetDlgItemText(AfxGetMainWnd()-m_hWnd,IDC_TIME,strTime); Sleep(1000); 该 线 程 函 数 没 有 参 数 ,也 不 返 回 函 数 值 。只 要 m_bRun为 TRUE ,线 程 一直 运 行 。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 35 页 - - - - - - - - - 双 击 IDC_START按 钮 , 完 成 该 按 钮 的 消 息 函 数 :vo
19、id CMultiThread1Dlg:OnStart() / TODO: Add your control notification handler code here hThread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, &ThreadID); GetDlgItem(IDC_START)-EnableWindow(FALSE); GetDlgItem(IDC_STOP)-EnableWindow(TRUE); 双 击 IDC_STOP按 钮 , 完 成 该 按 钮 的 消 息 函 数 :void
20、 CMultiThread1Dlg:OnStop() / TODO: Add your control notification handler code here m_bRun=FALSE; GetDlgItem(IDC_START)-EnableWindow(TRUE); GetDlgItem(IDC_STOP)-EnableWindow(FALSE); 编 译 并 运 行 该 例 程 , 体 会 使 用 Win32 API编 写 的 多 线 程 。例 程 2 MultiThread2 该 线 程 演 示 了 如 何 传 送 一 个 一 个 整 型 的 参 数 到 一 个 线 程 中 ,
21、以 及 如 何 等 待 一个 线 程 完 成 处 理 。1.建 立 一 个 基 于 对 话 框 的 工 程 MultiThread2, 在 对 话 框IDD_MULTITHREAD2_DIALOG中 加 入 一 个 编 辑 框 和 一 个 按 钮 ,ID 分 别 是IDC_COUNT, IDC_START , 按 钮 控 件 的 标 题 为 “ 开 始 ” ;2.在 MultiThread2Dlg.h文 件 中 添 加 线 程 函 数 声 明 :3.void ThreadFunc(int integer); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - -
22、- - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 35 页 - - - - - - - - - 注 意 , 线 程 函 数 的 声 明 应 在 类 CMultiThread2Dlg的 外 部 。在 类 CMultiThread2Dlg内 部 添 加 protected型 变 量 : HANDLE hThread; DWORD ThreadID; 分 别 代 表 线 程 的 句 柄 和 ID 。4.打 开 ClassWizard,为 编 辑 框 IDC_COUNT添 加 int型 变 量 m_nCount。在MultiThread2Dlg.cpp文 件 中 添
23、 加 :void ThreadFunc(int integer) int i; for(i=0;iEnableWindow(FALSE); WaitForSingleObject(hThread,INFINITE); GetDlgItem(IDC_START)-EnableWindow(TRUE); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 35 页 - - - - - - - - - 顺 便 说 一 下 WaitForSingleObject函 数 , 其 函 数
24、 原 型 为 :DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds); ohHandle为 要 监 视 的 对 象( 一 般 为 同 步 对 象 ,也 可 以 是 线 程 )的 句柄 ;odwMilliseconds为 hHandle对 象 所 设 置 的 超 时 值 , 单 位 为 毫 秒 ;当 在 某 一 线 程 中 调 用 该 函 数 时 , 线 程 暂 时 挂 起 , 系 统 监 视 hHandle所 指 向 的 对 象 的 状 态 。如 果 在 挂 起 的 dwMilliseconds毫 秒 内 ,线 程 所 等
25、 待的 对 象 变 为 有 信 号 状 态 , 则 该 函 数 立 即 返 回 ; 如 果 超 时 时 间 已 经 到 达dwMilliseconds毫 秒 , 但 hHandle所 指 向 的 对 象 还 没 有 变 成 有 信 号 状 态 ,函 数 照 样 返 回 。 参 数 dwMilliseconds有 两 个 具 有 特 殊 意 义 的 值 : 0 和INFINITE。 若 为 0, 则 该 函 数 立 即 返 回 ; 若 为 INFINITE, 则 线 程 一 直 被挂 起 , 直 到 hHandle所 指 向 的 对 象 变 为 有 信 号 状 态 时 为 止 。本 例 程 调
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年多线程编程基础 2022 多线程 编程 基础
限制150内