转载:

https://blog.csdn.net/yss28/article/details/53646627


《Win32多线程程序设计》–Jim Beveridge & Robert Wiener

“等待某个什么东西”是线程常常需要做的事。等待是线程的“必要之恶”

如果你没有等待线程结束就莽撞地结束程序,线程会被系统强制结束掉——在它完成它的工作之前。

由于让线程停工是操作系统的责任,很合理地我们会认为操作系统也有责任让其他线程知道某个线程停工了。

Sleep()

这个函数要求操作系统中止线程动作,直到渡过某个指定时间之后才恢复。

#include <stdio.h>
#include <Windows.h> DWORD WINAPI Thread(void *arg) {
// doing something
return 0;
} int main(void) {
HANDLE hThread = CreateThread(NULL, 0, Thread, NULL, 0, NULL);
Sleep(?); // 不可能事先知道要等待Thread多久
CloseHandle(hThread);
return 0;
}

GetExitCodeThread()轮询检查

使用 GetExitCodeThread() 可以决定一个线程是否还在执行。

#include <stdio.h>
#include <Windows.h> DWORD WINAPI Thread(void *arg) {
// doing something
return 0;
} int main(void) {
DWORD exitCode = 0;
HANDLE hThread = CreateThread(NULL, 0, Thread, NULL, 0, NULL);
while (1) {
GetExitCodeThread(hThread, &exitCode); // 严重浪费 CPU 时间
if (STILL_ACTIVE != exitCode)
break;
}
CloseHandle(hThread);
return 0;
}

WaitForSingleObject()

可看成一个新版的 Sleep() ,它能够在某个线程结束时(而不是某段时间结束时)被调用

可使用的核心对象有两种状态:激发未激发。WaitForSingleObject() 会在目标物变成激发状态时返回。

对象 说明
Thread(线程) 当线程结束时,线程对象即被激发。当线程还在进行时,则对象处于未激发状态。
Process(进程) 当进程结束时,进程对象即被激发。当进程还在进行时,则对象处于未激发状态。
Event Event 对象的状态直接受控于应用程序所使用的三个Win32函数:SetEvent()、PulseEvent()、ResetEvent()。CreateEvent()和OpenEvent()都可以传回一个event object handle。Event对象的状态也可以被操作系统设定。
Mutex 如果mutex没有被任何线程拥有,它就是处于激发状态。一旦一个等待mutex的函数返回了,mutex也就自动重置为未激发状态。
Semaphore Semaphore有点像mutex,但它有个计数器,可以约束其拥有者(线程)的个数。当计数器内容大于 0时,semaphore处于激发状态,当计数器内容等于0时,semaphore处于未激发状态。
#include <stdio.h>
#include <Windows.h> DWORD WINAPI Thread(void *arg) {
// doing something
return 0;
} int main(void) {
HANDLE hThread = CreateThread(NULL, 0, Thread, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE); // 等待,直到线程被激发
CloseHandle(hThread);
return 0;
}

WaitForMultipleObjects()

允许你在同一时间等待一个以上的对象。你必须将一个由 handles 组成的数组交给此函数,并指定要等待其中一个对象或是全部的对象

(范例:保持线程池中始终有3个线程在运行)

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h> #define POOL_SIZE 3 // 线程池大小
#define TASK_NUM 6 DWORD WINAPI ThreadFunc(LPVOID n) {
srand(GetTickCount()); Sleep(rand()%5000+500);
printf("%d over\n", n);
return ((DWORD)n);
} int main(void){
HANDLE hThrds[POOL_SIZE];
int pIdx = 0, tIdx;
DWORD rc; for (tIdx = 1; tIdx <= TASK_NUM; tIdx++) {
if (tIdx > POOL_SIZE) {
rc = WaitForMultipleObjects(POOL_SIZE, hThrds, FALSE, INFINITE); // 等待hThrds数组中任意一个变为激发状态,返回其索引
pIdx = rc - WAIT_OBJECT_0;
assert(pIdx >= 0 && pIdx < POOL_SIZE);
printf("%d terminated\n", pIdx);
CloseHandle(hThrds[pIdx]);
} hThrds[pIdx++] = CreateThread(NULL, 0, ThreadFunc, (LPVOID)pIdx, 0, NULL);
printf("Thread #%d launched (pIdx %d)\n", tIdx, pIdx);
} WaitForMultipleObjects(POOL_SIZE, hThrds, TRUE, INFINITE); // 等待hThrds数组中所有线程变为激发状态
for (pIdx = 0; pIdx < POOL_SIZE; pIdx++)
CloseHandle(hThrds[pIdx]); return EXIT_SUCCESS;
}

结果:

GUI 程序中等待

Windows 程序中的“主消息循环”看起来像这个样子:

while (GetMessage(&msg, NULL, 0, 0,))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

GetMessage() 有点像是特殊版本的 WaitForSingleObject(),它等待消息

不是核心对象。一旦你调用 GetMessage() ,除非有一个消息真正进入你的消息

队列( message queue )之中,否则它不会返回。

如果你在主线程中正使用 WaitForSingleO bject()或 WaitForMultipleObjects()等待某个对象被激发,你根本没有办法回到主消息循环中去。

为了解决这个问题,主消息循环必须修改,使它得以同时等待消息或是核心对象被激发。你必须使用一个 MsgWaitForMultipleObjects() 函数。这个函数非常类似WaitForMultipleObjects(),但它会在“对象被激发”或“消息到达队列”时被唤醒而返回。MsgWaitForMultipleObjects() 多接受一个参数,允许指定哪些消息是观察对象。

Win32线程——等待另一个线程结束的更多相关文章

  1. join当前线程等待指定的线程结束后才能继续运行

    模拟一个QQ游戏大厅斗地主 /** sleep(休眠.睡眠) join当前线程等待指定的线程结束后才能继续运行 */ class Player extends Thread{ private Stri ...

  2. .NET一个线程更新另一个线程的UI(两种实现方法及若干简化)

    Winform中的控件是绑定到特定的线程的(一般是主线程),这意味着从另一个线程更新主线程的控件不能直接调用该控件的成员. 控件绑定到特定的线程这个概念如下: 为了从另一个线程更新主线程的Window ...

  3. Java 实现缓存,一个线程存,一个线程取

    缓存类: package com.zit.test; import java.util.concurrent.BlockingDeque; import java.util.concurrent.Li ...

  4. 线程等待 Join()方法

    Join()方法是让一个线程等待另一个线程的完成 下面看个例子: package project11; public class TestJoin extends Thread { public vo ...

  5. java 线程实现、线程暂停和终止 、线程联合join、线程基本信息获取和设置、线程优先级

    转载地址:速学堂 https://www.sxt.cn/Java_jQuery_in_action/eleven-inheritthread.html 1. 通过继承Thread类实现多线程 继承Th ...

  6. 廖雪峰Java11多线程编程-1线程的概念-3线程的状态

    1线程的状态 线程终止的的原因: run()或call()方法执行完成,线程正常结束 线程抛出一个未捕获的Exception或Error 直接调用该线程的stop()方法来结束该线程--该方法容易导致 ...

  7. Thread线程源码解析,Java线程的状态,线程之间的通信

    线程的基本概念 什么是线程 现代操作系统在运行一个程序的时候,会为其创建一个进程.例如,启动一个Java程序,操作系统就会创建一个Java进程.线代操作系统调度的最小单位是线程.也叫做轻量级进程.在一 ...

  8. c/c++ 多线程 一个线程等待某种事件发生

    多线程 一个线程等待某种事件发生 背景:某个线程在能够完成其任务之前可能需要等待另一个线程完成其任务. 例如:坐夜间列车,为了能够不坐过站, 1,整夜保持清醒,但是这样你就会非常累,不能够睡觉. 2, ...

  9. Linux多线程(二)(线程等待,退出)

    1. 线程的等待退出 1.1. 等待线程退出 线程从入口点函数自然返回,或者主动调用pthread_exit()函数,都可以让线程正常终止 线程从入口点函数自然返回时,函数返回值可以被其它线程用pth ...

随机推荐

  1. spring boot中实现security错误信息本地化

    一.修改messages.properties 找源码中的messages.properties,复制一份放在classpath下,修改你要修改的内容 AbstractUserDetailsAuthe ...

  2. [cf contest697] D - Puzzles

    [cf contest697] D - Puzzles time limit per test 1 second memory limit per test 256 megabytes input s ...

  3. swarm 使用整理

    swarm 是 docker 公司弄的 docker 集群管理工具.  整理使用实践如下. 1. 准备 3 台实例机   ip 地址分别是 192.168.0.131    ~   1332. 在三台 ...

  4. https环境搭建(本地搭建)

    1.创建自签名证书 2. 在iis中绑定https 先解析一个域名. 运行网站 示不安全,点击继续浏览即可.在实际的环境中,你拿到的是一个实际的证书,所以不会产生类似的报告安全证书有问题.

  5. element 树形菜单加title

    <script src="//unpkg.com/vue/dist/vue.js"></script><script src="//unpk ...

  6. 《程序设计入门——C语言》翁恺老师 第二周编程练习记录

    1 逆序的三位数(5分) 题目内容: 逆序的三位数: 程序每次读入一个正三位数,然后输出逆序的数字.注意,当输入的数字含有结尾的0时,输出不应带有前导的0.比如输入700,输出应该是7. 提示:用%1 ...

  7. inotify事件监控工具

    inotify事件监控工具   rsync + inotify 组合的起源   inotify优缺点 优点:监控文件系统事件变化,通过同步工具实现实时数据同步 缺点:并发如果大于200个文件(10-1 ...

  8. python运算符与数据类型

    python运算符 Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算符 成员运算符 身份运算符 运算符优先级 以下假设变量: a=10,b=20: ...

  9. Python-点滴

    本节内容: python简介 安装(python,pycharm) 第一个程序(Hello,World!) 变量 用户输入 字符编码 格式化输出 if流程控制 while循环 for循环 一.Pyth ...

  10. 使用Python统计函数绘制简单图形matplotlib

    1.bar() -- 绘制柱状图 plt.bar(x,y,align="center",color="b",tick_label=["a", ...