线程调度

线程内核对象中有个叫做挂起计数的东西
每次调用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
);

你可能感兴趣的:(线程调度)