线程控制
控制一个线程,就要用到其他的API,所以本章就说说那些常用的控制线程的部分API
让自己停下来(本线程):
Sleep
VOID Sleep(
DWORD dwMilliseconds // sleep time
);
让线程停止多少毫秒
让别人停下来(其他线程):
SuspendThread
DWORD SuspendThread(
HANDLE hThread // handle to thread
);
让线程变成挂起状态,挂起状态的计数器+1
线程恢复
ResumeThread
DWORD ResumeThread(
HANDLE hThread // handle to thread
);
让线程恢复执行的状态,挂起状态的计数器-1
代码实验
#include<stdio.h>
#include<Windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
for (int i = 0 ; i < 100; i++)
{
Sleep(500);
printf("+++++++++++++++%d\n", i);
}
return 0;
}
int main()
{
HANDLE hThread;
hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
Sleep(5000); //停下5秒
SuspendThread(hThread);
Sleep(5000);
ResumeThread(hThread);
getchar(); //让控制台显示输出
CloseHandle(hThread);
return 0;
}
这里用的在按个线程用的Sleep就停的那个线程,别搞混了
然后继续,每当线程执行完毕,我怎么知道这个线程执行完毕了?
新的API来啦
WaitForSingleObject
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
他会阻塞你给的线程,什么时候停止呢?当他判断该线程变更的时候,即线程执行完毕了,就会返回,继续向下执行
这里你可以设置时间,第二个参数就是,超过设定的时间,他也会返回
如果想让他一直等待,给他个宏:INFINITE
实验
#include<stdio.h>
#include<Windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
for (int i = 0 ; i < 100; i++)
{
Sleep(50);
printf("+++++++++++++++%d\n", i);
}
return 0;
}
int main()
{
HANDLE hThread;
hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
WaitForSingleObject(hThread,INFINITE);
printf("线程执行完毕\n");
getchar();
CloseHandle(hThread);
return 0;
}
会发现会一直等待线程执行完才打印执行完毕
这个函数只能等待某一个内核对象的状态发生变更,如果我有两个线程,我要想让两个线程都做完了,才打印,那么又来啦,新API
DWORD WaitForMultipleObjects(
DWORD nCount, // number of handles in array
CONST HANDLE *lpHandles, // object-handle array
BOOL fWaitAll, // wait option
DWORD dwMilliseconds // time-out interval
);
- 第一个参数:你要等几个内核对象
- 第二个参数:内核对象的数组
- 第三个参数:等待模式,可以指定所有的等待对象都发生变更才返回即为TRUE,也可以任意一个对象发生变更就返回即为FALSE
- 第四个参数:等待时间
实验
#include<stdio.h>
#include<Windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
for (int i = 0 ; i < 100; i++)
{
Sleep(50);
printf("+++++++++++++++%d\n", i);
}
return 0;
}
int main()
{
HANDLE hThread[2];
hThread[0] = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
hThread[1] = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
WaitForMultipleObjects(2,hThread,TRUE,INFINITE);
printf("线程执行完毕\n");
getchar();
CloseHandle(hThread);
return 0;
}
也是能成功执行
这次来细嗦CreateThread函数的返回值
这个函数值可以自己设置,比如创建成功返回一个值,失败一个值,那么就可以用下面的API来接收
GetExitCodeThread
BOOL GetExitCodeThread(
HANDLE hThread, // handle to the thread
LPDWORD lpExitCode // termination status
);
第一个句柄,第二个就是返回值了,是个out参数
代码
#include<stdio.h>
#include<Windows.h>
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
for (int i = 0 ; i < 100; i++)
{
Sleep(50);
printf("+++++++++++++++%d\n", i);
}
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
for (int i = 0 ; i < 100; i++)
{
Sleep(50);
printf("+++++++++++++++%d\n", i);
}
return 1;
}
int main()
{
DWORD dwre1;
DWORD dwre2;
HANDLE hThread[2];
hThread[0] = CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
hThread[1] = CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
GetExitCodeThread(hThread[0],&dwre1);
GetExitCodeThread(hThread[1],&dwre2);
getchar();
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
return 0;
}
我们都说如果只有一个核的时候怎么切换线程,那里面的信息怎么保存呢,总不可能不回来吧。
每一个线程都有结构体,当自己被切换的时候,就会把自己运行的信息存储到该结构体
CONTEXT
俗称:线程上下文,点F12,就可以看到是 一堆寄存器
要获取这些信息要先把他挂起
#include<stdio.h>
#include<Windows.h>
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
/*
for (int i = 0 ; i < 100; i++)
{
Sleep(50);
printf("+++++++++++++++%d\n", i);
}*/
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
for (int i = 0 ; i < 100; i++)
{
Sleep(50);
printf("+++++++++++++++%d\n", i);
}
return 1;
}
int main()
{
HANDLE hThread[2];
hThread[0] = CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
//hThread[1] = CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
SuspendThread(hThread[0]);
CONTEXT context;
context.ContextFlags = CONTEXT_INTEGER;
GetThreadContext(hThread[0],&context);
printf("%x %x\n",context.Eax,context.Ecx);
ResumeThread(hThread[0]);
getchar();
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
return 0;
}
由于寄存器较多,需要设置一下flag,如图
这里我去调试了一下,发现与调试显示的并不是一样的,请大佬解释一下
获取线程上下文:
GetThreadContext
BOOL GetThreadContext(
HANDLE hThread, // handle to thread with context
LPCONTEXT lpContext // context structure
);
设置线程上下文
SetThreadContext
BOOL SetThreadContext(
HANDLE hThread, // handle to thread
CONST CONTEXT *lpContext // context structure
);
总结
各种的API函数的使用