线程内核对象中有个叫做挂起计数的东西
每次调用CreateProcess或者CreateThread时
这个东西就会在线程内核对象创建后初始化为1
然后在线程初始化完成前 就不会被调度了
然后在初始化之后 CreateProcess和CreateThread会检查有没有CREATE_SUSPENDED标志传入
有的话函数就会将这个线程挂起 没有则挂起计数会变0
然后线程就可以被调度了
对于处于挂起状态的线程 我们可以在线程执行任何代码前改变它的环境(如优先级)
然后就是把线程变成可调度的的方法:
调用ResumeThread函数 传入线程句柄
成功将返回线程的前一个挂起计数 失败则返回0xFFFFFFFF
一个线程可以多次挂起 挂起多少次就要Resume多少次才能调度
DWORD ResumeThread(HANDLE hThread);
另外还可以通过SuspendThread函数来挂起线程
DWORD SuspendThread(HANDLE hThread);
这个函数的返回值和ResumeThread相同
(一个线程最多可以挂起MAXIMUM_SUSPEND_COUNT次[WinNT.h中定义为127])
进程的挂起和恢复(并不存在的概念)
这是一个挂起进程中所有线程的问题
虽然没有现成的比较好的函数
但是我们可以自己写一个
VOID SuspendProcess(DWORD dwProcessID, BOOL fSuspend) {
HANDLE hThreadSnapShot = INVALID_HANDLE_VALUE;
THREADENTRY32 te32 = {sizeof(te32)};
hThreadSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);
if (hThreadSnapShot != INVALID_HANDLE_VALUE) {
Thread32First(hThreadSnapShot, &te32);
do {
if (te32.th32OwnerProcessID == dwProcessID) {
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID);
if (hThread != NULL) {
if (fSuspend) {
SuspendThread(hThread);
}else{
ResumeThread(hThread);
}
}
CloseHandle(hThread);
}
}while (Thread32Next(hThreadSnapShot, &te32));
CloseHandle(hThreadSnapShot);
}
}
线程还可以干一件叫做睡眠的事情 大概就是一段时间内不接受调度的(傲娇)行为
VOID Sleep(DWORD dwMilliseconds);
具体作用就是会停止dwMilliseconds ms的时间
如果传入0的话 其实就是强制系统去调用另外一个线程(然后这个线程还可以调度 嗯标准傲娇)
切换到另一个线程的方法:
使用函数SwitchToThread()
这是一个并没有参数的函数
所以有必要解释一下调用时会发生什么:
首先系统会查看是否存在急需CPU时间的饥饿进程
- 没有:立即返回
- 有:调度这个线程
那么这个函数和Sleep(0)的作用的区别在哪儿呢= =
答案是 Sleep(0)之后系统会运行优先级最高的线程
SwitchToThread允许运行优先级比自己低的线程
有时候需要计算线程运行的时间
一般的做法(误):
ULONGLONG qwStartTime = GetTickCount64();
...(somethings needed to do)
ULONGLONG qwElapsedTime = GetTickCount64() - qwStartTime;
这样做表面看并没有问题 但问题是windows是个抢占式的系统
所以。。就会坑
于是你需要使用
BOOL GetThreadTimes (
HANDLE hThread,
LPFILETIME lpCreationTime,
LPFILETIME lpExitTime,
LPFILETIME lpKernelTime,
LPFILETIME lpUserTime
);
网友评论