线程可警告状态以及APC队列
2017-08-22 10:56
211 查看
转自:http://blog.csdn.net/qq_22423659/article/details/53425828
一、线程可警告状态的真实含义
1、通过另一些方法让线程"暂停"(非SuspendThread方法,比如SleepEx,wait函数族等),并可以进入一种称之为
Alterable的状态(可警告状态)
2、这种状态本质上其实是高速系统调度程序:当前现成的函数调用栈以及对应的寄存器状态可以直接被用来调用
别的一些函数,一般这种函数都被称为异步函数
3、通常系统会用此线程环境(理解为函数调用器)来调用一些其他的回调函数(比如:IO完成通知,线程的异步调用队列等)
4、这样借用线程的好处是,系统不必为一些回调函数大费周折的创建一些新的专用线程,既可以达到节约系统资源的目的,
还可以充分发挥系统性能
5、通常异步函数最好能够很快执行完,不要做太耗时的操作,不然真正的线程函数需要执行时,会无法立即执行
参考视频:点击打开链接
二、线程APC队列
1、每个线程可以通过调用QueueUserAPC函数,明确的创建一个"异步调用队列"
2、其实就是为线程在线程函数调用栈之外再安排一组函数去执行
3、默认情况下,创建线程时不会创建这个队列,当调用该函数时,就会为这个线程创建这个队列
4、创建APC队列的函数,一般使用Wait函数族或者SleepEx函数等带有bAlertable参数的函数进入一种假"暂停"的状态
5、进入Alertable状态的线程,系统调度器会在线程函数本身处于"暂停"(等待状态)时,一次调用线程APC队列中的函数
6、注意APC队列中的函数不要执行事件过长,以免影响线程函数本身的执行
7、需要注意的是,有些函数虽然也会使线程进入等待状态,但不能进入可警告状态,也即不能调用异步的函数,比如:
GetMessage函数等(这些函数也没有bAlterable参数)
8、最后也需要注意的是,不要在APC函数中再调用让线程进入Alterable状态的API,这会引起一个递归,而导致线程栈溢出
[cpp] view
plain copy
/*
演示了ThreadAlerable如何让一个线程进入可警告状态并去执行一个APC队列中的函数
*/
#include<windows.h>
#include<tchar.h>
#include<strsafe.h>
#define GRS_USEPRINTF() TCHAR pBuf[1024]={}
#define GRS_PRINTF(...)\
StringCchPrintf(pBuf, 1024, __VA_ARGS__); \
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pBuf, lstrlen(pBuf), NULL, NULL);
void CALLBACK APCFunction(ULONG_PTR dwParam)
{
int i = dwParam;
GRS_USEPRINTF();
GRS_PRINTF(_T("%d APC Function Run!\n"),i);
Sleep(20);
}
int _tmain()
{
//为主线程添加APC函数
for (int i = 0; i < 100; i++)
{
QueueUserAPC(APCFunction,GetCurrentThread(),i);//为当前线程创建APCFunction的队列
}
//通过SleepEx进入"可警告状态",注释后,APC函数不会被调用
//SleepEx使主线程进入等待,执行APC函数
SleepEx(10000,TRUE);
_tsystem(_T("PAUSE"));
return 0;
}
一、线程可警告状态的真实含义
1、通过另一些方法让线程"暂停"(非SuspendThread方法,比如SleepEx,wait函数族等),并可以进入一种称之为
Alterable的状态(可警告状态)
2、这种状态本质上其实是高速系统调度程序:当前现成的函数调用栈以及对应的寄存器状态可以直接被用来调用
别的一些函数,一般这种函数都被称为异步函数
3、通常系统会用此线程环境(理解为函数调用器)来调用一些其他的回调函数(比如:IO完成通知,线程的异步调用队列等)
4、这样借用线程的好处是,系统不必为一些回调函数大费周折的创建一些新的专用线程,既可以达到节约系统资源的目的,
还可以充分发挥系统性能
5、通常异步函数最好能够很快执行完,不要做太耗时的操作,不然真正的线程函数需要执行时,会无法立即执行
参考视频:点击打开链接
二、线程APC队列
1、每个线程可以通过调用QueueUserAPC函数,明确的创建一个"异步调用队列"
2、其实就是为线程在线程函数调用栈之外再安排一组函数去执行
3、默认情况下,创建线程时不会创建这个队列,当调用该函数时,就会为这个线程创建这个队列
4、创建APC队列的函数,一般使用Wait函数族或者SleepEx函数等带有bAlertable参数的函数进入一种假"暂停"的状态
5、进入Alertable状态的线程,系统调度器会在线程函数本身处于"暂停"(等待状态)时,一次调用线程APC队列中的函数
6、注意APC队列中的函数不要执行事件过长,以免影响线程函数本身的执行
7、需要注意的是,有些函数虽然也会使线程进入等待状态,但不能进入可警告状态,也即不能调用异步的函数,比如:
GetMessage函数等(这些函数也没有bAlterable参数)
8、最后也需要注意的是,不要在APC函数中再调用让线程进入Alterable状态的API,这会引起一个递归,而导致线程栈溢出
[cpp] view
plain copy
/*
演示了ThreadAlerable如何让一个线程进入可警告状态并去执行一个APC队列中的函数
*/
#include<windows.h>
#include<tchar.h>
#include<strsafe.h>
#define GRS_USEPRINTF() TCHAR pBuf[1024]={}
#define GRS_PRINTF(...)\
StringCchPrintf(pBuf, 1024, __VA_ARGS__); \
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pBuf, lstrlen(pBuf), NULL, NULL);
void CALLBACK APCFunction(ULONG_PTR dwParam)
{
int i = dwParam;
GRS_USEPRINTF();
GRS_PRINTF(_T("%d APC Function Run!\n"),i);
Sleep(20);
}
int _tmain()
{
//为主线程添加APC函数
for (int i = 0; i < 100; i++)
{
QueueUserAPC(APCFunction,GetCurrentThread(),i);//为当前线程创建APCFunction的队列
}
//通过SleepEx进入"可警告状态",注释后,APC函数不会被调用
//SleepEx使主线程进入等待,执行APC函数
SleepEx(10000,TRUE);
_tsystem(_T("PAUSE"));
return 0;
}
相关文章推荐
- windows核心编程-线程可警告状态以及APC队列
- Windows APC机制 & 可警告alertable的线程等待状态
- day10 反射创建数组 线程的基本概念 线程的编写和启动方式 线程的运行状态以及状态转换方法 线程的调度和优先级设置
- Java线程安全杂谈——锁、状态依赖与协同以及锁优化
- 多线程 - 04.线程状态以及线程安全
- 线程的7种状态及相互转换(图)以及关于线程同步(7种同步方式)
- Java线程状态转换的方法以及它们的区别
- 线程的创建 以及 线程的各种状态
- java线程中的几种状态以及相互转换
- Java多线程:线程状态以及wait(), notify(), notifyAll()
- 线程的基本概念、线程的基本状态以及状态之间的关系
- JAVA线程状态以及synchronized,wait,sleep,yield,notify,notifyAll
- 可延迟函数、内核微线程以及工作队列
- ios-创建线程的基本方法和线程的状态以及属性
- 多线程:线程状态、synchronized关键字、读写锁、条件对象、Volatile、阻塞队列等小结
- Java多线程之线程的五种状态以及状态之间的关系
- 内核 API,第 2 部分:可延迟函数、内核微线程以及工作队列
- 线程的状态以及状态间的转换
- Java多线程之中断线程、中断状态以及间隔输出
- 线程的7种状态以及相互转换