2021-03-09Win3200
请注意,本文编写于 630 天前,最后修改于 624 天前,其中某些信息可能已经过时。

目录


1. 如何让线程停下来?

c
让自己停下来:
	Sleep()函数

让别人停下来:
	SuspendThread()函数,一个线程可以挂起多次,可以连续挂起

线程恢复:
	ResumeThread()函数
c
# include <stdio.h>
# include <Windows.h>
# include <stdlib.h>


int flag = 0;
int a;

DWORD WINAPI LOOP(LPVOID lp)
{
	while (true)
	{
		a = 1 + 1;
		printf("子线程a = %d\r\n", a);
		Sleep(2000);
	}
}

int main()
{
	HANDLE hThread = CreateThread(NULL, 0, LOOP, NULL, 0, NULL);
	int b = 5;
	while (true)
	{
		printf("主线程b = %d\r\n",b);
		Sleep(2000);
		flag++;
		if (flag == 5)
		{
			//用于暂停线程,参数就是线程句柄
			SuspendThread(hThread);
		}
		if (flag == 10)
		{
			//用于恢复线程,参数就是线程句柄
			ResumeThread(hThread);
		}
	}
	return 0;
}

2. 等待线程结束

<1> WaitForSingleObject();

c
DWORD WaitForSingleObject(
    HANDLE hHandle,
    DWORD dwMilliseconds );          //等待时间,超时时间

参数 hHandle 是一个事件的句柄,
第二个参数 dwMilliseconds 是时间间隔。
如果时间是有信号状态返回 WAIT_OBJECT_0 ,如果时间超过 dwMilliseconds 值但时间事件还是无信号状态则返回 WAIT_TIMEOUT

<2> WaitForMultipleObjects();

c
等待多个内核对象
DWORD WaitForMultipleObjects(
    DWORD nCount,                //等几个内核对象
    CONST HANDLE *lpHandles,     //等待的内核对象数组
    BOOL fWaitAll,               //等待模式,1. 可以指定所有的等待对象都发生变更的时候返回,2.有任何一个等待对象发生变更即返回
    DWORD dwMilliseconds );      //等待时间,超时时间

<3> GetExitCodeThread();

c
用于获取一个已中止线程的退出代码。
BOOL  GetExitCodeThread (
      HANDLE        hThread,        // in,线程handle,也就是CreateThread()的返回值
      LPDWORD     lpExitCode        //out,存储线程结束代码,也就是线程的返回值
);

3. 设置、获取线程上下文:

CONTEXT结构包含了特定处理器的寄存器数据。系统使用 CONTEXT结构执行各种内部
操作。目前,已经存在为 Intel、MIPS、Alpha和PowerPC处理器定义的CONTEXT结构。

c
BOOL GetThreadContext(
  HANDLE hThread,       // handle to thread with context
  LPCONTEXT lpContext   // context structure
);

BOOL SetThreadContext(
  HANDLE hThread,            // handle to thread
  CONST CONTEXT *lpContext   // context structure
);
c
# include <stdio.h>
# include <Windows.h>
# include <stdlib.h>


DWORD WINAPI ThreadFunc(LPVOID lp);

int main()
{

    HANDLE hThread;
    hThread = CreateThread(NULL, 0, ThreadFunc, 0, 0, NULL);

    //获取
    CONTEXT ThreadContext;
    //ThreadContext.ContextFlags = CONTEXT_CONTROL;    //CONTEXT_CONTROL获取控制寄存器
    //ThreadContext.ContextFlags = CONTEXT_INTEGER;    //CONTEXT_INTEGER获取整数寄存器
    //ThreadContext.ContextFlags = CONTEXT_FULL;       //同时获取CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS
    ThreadContext.ContextFlags = CONTEXT_ALL;          //获取所有寄存器
    GetThreadContext(hThread, &ThreadContext);

    //修改EAX寄存器
    ThreadContext.Eax = 0x12138;
    ThreadContext.ContextFlags = CONTEXT_ALL;
    SetThreadContext(hThread, &ThreadContext);

    //重新获取,用于确认
    ThreadContext.ContextFlags = CONTEXT_ALL;          //获取所有寄存器
    GetThreadContext(hThread, &ThreadContext);

    system("pause");
    return 0;
}

DWORD WINAPI ThreadFunc(LPVOID lp)
{
    for (size_t i = 0; i < 10000; i++)
    {
        printf("\r\n");
    }
    return 0;
}

本文作者:Na1r

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!