Win32 - 线程控制

1.如何让线程停下来?

Sleep() 自己停下来

SuspendThread(Handle) //挂起别人的进程

ResumeThread(Handle) //复活别人的进程

#include "stdafx.h"
#include <windows.h>
DWORD WINAPI ThreadProc(LPVOID lpparameter){
	
	for(int i = 50;i > 0 ;i--){
		Sleep(500);
		printf("-----%d\n",i);
	}
	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hThread;
	hThread = CreateThread(0,0,ThreadProc,NULL,0,0);
	Sleep(2000); //挂起自己2s
	SuspendThread(hThread); //挂起创建的线程
	//SuspendThread(hThread); //挂起多少次,就要恢复多少次
	Sleep(5000); //挂起自己25s
	ResumeThread(hThread); //恢复线程
	getchar();
	return 0;
}



2.等待线程结束:

DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD  dwMilliseconds
);
/*
hHandle
Waits until the specified object is in the signaled state or the time-out interval elapses.

To enter an alertable wait state, use the WaitForSingleObjectEx function. To wait for multiple objects, use WaitForMultipleObjects.

dwMilliseconds

The time-out interval, in milliseconds. If a nonzero value is specified, the function waits until the object is signaled or the interval elapses. If dwMilliseconds is zero, the function does not enter a wait state if the object is not signaled; it always returns immediately. If dwMilliseconds is INFINITE, the function will return only when the object is signaled.
*/

DWORD WaitForMultipleObjects(
  DWORD        nCount, //The number of object handles in the array pointed to by lpHandles
  const HANDLE *lpHandles, //An array of object handles. For a list of the object types whose handles can be specified, see the following Remarks section. 
  BOOL         bWaitAll,
  DWORD        dwMilliseconds
);
/*
The number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS. This parameter cannot be zero.
*/
BOOL GetExitCodeThread(
  HANDLE  hThread,
  LPDWORD lpExitCode 
);
/*
	Retrieves the termination status of the specified thread.
	
	

lpExitCode->A pointer to a variable to receive the thread termination status. For more information, see Remarks.

Return value
If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call
*/

code 线程的返回值

#include "stdafx.h"
#include <windows.h>

DWORD WINAPI ThreadProc(LPVOID lpparameter){
	
	for(int i = 50;i > 0 ;i--){
		Sleep(50);
		printf("1-----%d\n",i);
	}
	return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpparameter){

	for(int i = 50;i > 0 ;i--){
		Sleep(50);
		printf("2-----%d\n",i);
	}
	return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE ArrhThread[2];
	DWORD Results[2];
	ArrhThread[0] = CreateThread(0,0,ThreadProc,NULL,0,0);
	ArrhThread[1] = CreateThread(0,0,ThreadProc2,NULL,0,0); //俩份堆栈
	//WaitForSingleObject(hThread,INFINITE);  //只是等待这个线程2000ms,而不会关闭这个线程
	WaitForMultipleObjects(2,ArrhThread,1,INFINITE);
	GetExitCodeThread(ArrhThread[0],&Results[0]);
	GetExitCodeThread(ArrhThread[1],&Results[1]); //线程没有运行完的话,就取返回结果 会出错
	printf("线程hThread 执行完毕\n");
	printf("Thread 1 return:%d \nThread 2 return :%d\n",Results[0],Results[1]);
	getchar();
	return 0;
}

1587740960409


3.设置线程 上下文

考虑一种情况,如果我们的计算机CPU是单核的, 那么我们的线程是来回切换着执行的.

那么CPU切换线程过程中, cpu是如何保存现场(各种寄存器值) 和 恢复现场(各种寄存器的值)的呢?

CPU中有一个结构 CONTEXT 专门用来保存线程的执行状态

//typedef struct _CONTEXT {
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread's
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//

DWORD ContextFlags;

//
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT
// included in CONTEXT_FULL.
//

DWORD   Dr0;
DWORD   Dr1;
DWORD   Dr2;
DWORD   Dr3;
DWORD   Dr6;
DWORD   Dr7;

//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
//

FLOATING_SAVE_AREA FloatSave;

//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//

DWORD   SegGs;
DWORD   SegFs;
DWORD   SegEs;
DWORD   SegDs;

//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//

DWORD   Edi;
DWORD   Esi;
DWORD   Ebx;
DWORD   Edx;
DWORD   Ecx;
DWORD   Eax;

//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_CONTROL.
//

DWORD   Ebp;
DWORD   Eip;
DWORD   SegCs;              // MUST BE SANITIZED
DWORD   EFlags;             // MUST BE SANITIZED
DWORD   Esp;
DWORD   SegSs;

//
// This section is specified/returned if the ContextFlags word
// contains the flag CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
//

BYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
}

打印一个线程的上下文:

GetThreadContext(
    __in    HANDLE hThread,
    __inout LPCONTEXT lpContext
    ); //获取线程的上下文,返回给你的指针
    
SetThreadContext(
    __in HANDLE hThread,
    __in CONST CONTEXT *lpContext
    ); //设置线程的上下文

测试线程上下文

DWORD WINAPI ThreadProc(LPVOID lpparameter){
	
	for(int i = 50;i > 0 ;i--){
		Sleep(50);
		printf("1-----%d\n",i);
	}
	return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpparameter){

	for(int i = 50;i > 0 ;i--){
		Sleep(50);
		printf("2-----%d\n",i);
	}
	return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE ArrhThread[2];
	DWORD Results[2];
	ArrhThread[0] = CreateThread(0,0,ThreadProc,NULL,0,0);
	
	SuspendThread(ArrhThread[0]);//Get线程上下文,线程必须处于挂起状态
	CONTEXT context;
	context.ContextFlags = CONTEXT_INTEGER; //上下文的寄存器较多,设置取你想要的寄存器选项
	GetThreadContext(ArrhThread[0],&context);
	printf("Thread.EAX:%x Thtead.EBX:%x \n",context.Eax,context.Ebx);
	getchar();
	return 0;
}

1587742249802

总结:每当CPU 切换线程的时候, CPU会把线程的各种寄存器存储到context上下文,然后切换线程.实现线程的交替执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Win32多线程中可以使用互斥量(Mutex)来控制执行顺序。互斥量是一个同步对象,用于限制对共享资源的访问。 当一个线程需要访问共享资源时,它必须先获得互斥量的所有权,然后才能访问共享资源。如果资源已经被其他线程占用,则该线程将被阻塞,直到资源可用为止。 以下是使用互斥量实现线程同步的示例: ```c++ #include <Windows.h> HANDLE hMutex; DWORD WINAPI ThreadFunc1(LPVOID lpParam) { // 等待互斥量 WaitForSingleObject(hMutex, INFINITE); // 访问共享资源 printf("Thread 1 is accessing the shared resource.\n"); // 释放互斥量 ReleaseMutex(hMutex); return 0; } DWORD WINAPI ThreadFunc2(LPVOID lpParam) { // 等待互斥量 WaitForSingleObject(hMutex, INFINITE); // 访问共享资源 printf("Thread 2 is accessing the shared resource.\n"); // 释放互斥量 ReleaseMutex(hMutex); return 0; } int main() { // 创建互斥量 hMutex = CreateMutex(NULL, FALSE, NULL); // 创建线程 HANDLE hThread1 = CreateThread(NULL, 0, ThreadFunc1, NULL, 0, NULL); HANDLE hThread2 = CreateThread(NULL, 0, ThreadFunc2, NULL, 0, NULL); // 等待线程完成 WaitForSingleObject(hThread1, INFINITE); WaitForSingleObject(hThread2, INFINITE); // 关闭句柄 CloseHandle(hMutex); CloseHandle(hThread1); CloseHandle(hThread2); return 0; } ``` 在上面的示例中,两个线程都需要访问共享资源,但是只有一个线程可以访问该资源。通过使用互斥量,我们可以确保线程之间的执行顺序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值