C++多线程之CreateThread

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013043408/article/details/83830598

WIN32API,需要包含头文件windows.h

API简介

简单了解下,平时用到的也就那两三个。

接口 简介
SwitchToThread 切换到另一个可调度线程
CreateThread 创建线程
CreateRemoteThread 创建远程线程
GetCurrentThread 获取线程句柄
GetCurrentThreadId 获取线程ID
OpenThread 打开一个现有线程对象
SetThreadPriority 设置线程优先级
GetThreadPriority 获取线程优先级
SetThreadPriorityBoost 设置开关–系统动态提升该线程的优先级
GetThreadPriorityBoost 获取~开关
ExitThread 在线程的执行过程中终止
TerminateThread 在线程的外面终止
GetExitCodeThread 获取一个已中止线程的退出代码
SuspendThread 暂停线程
ResumeThread 恢复线程
SetThreadStackGuarantee 要求系统在抛出EXCEPTION_STACK_OVERFLOW异常的时候,保证仍然有指定大小的空闲区可以用
WaitForSingleObject 阻塞,直到等到信号
CloseHandle 关闭句柄

CreateThread导致内存泄漏

根据百度来的,口水一下。C运行库中有许多全局变量,如错误码等。多个线程同时操作这些全局变量,就会出错(没同步)。所以,微软就给每个线程划分了自己存全局变量的空间,TLS(thread local storage)。这样,各用各的,就不会出错了。奇怪的是,CreateThread压根没TLS的概念,就不会创建这个内存。当在CreateThread创建的线程中要读写那些全局变量时,发现没有TLS,就会创建一个给自己用。可恨的是,CloseHandle中不会释放TLS。这样,内存就泄漏了。
所以,为了保险起见,创建线程使用C运行库中的_beginthread或_beginthreadex。

SuspendThread的计数规则

在测试中,对一个线程连续SuspendThread三次,然后ResumeThread一次,发现线程没有被唤醒。直到再ResumeThread两次后,线程才被唤醒。估计线程内有个计数,SuspendThread一次加一,ResumeThread一次减一。0表示线程可以执行啦,求CPU来拥抱。

自定义一个实用的线程类

一个理想的线程,当然是希望它自然退出,不能自然退出视为逻辑BUG。同时,能控制线程运行,挂起,唤醒和结束。至于优先级之类的,貌似手动设置不如系统优化。

公有方法

	//启动,线程初始状态为暂停。
	bool play();
	//暂停,同一线程,最多被SuspendThread一次。
	bool pause();
	//结束,若是暂停状态,先启动再让其自然退出。
	bool stop();
	//当前状态,启动|暂停|结束
	eState getState();

完整源码(也可下载完整测试工程)

.h

#pragma once

typedef void(*proc_type)(void*);

class ThreadWin
{
public:
	enum eState { PLAY = 1, PAUSE, STOP };

	friend unsigned __stdcall threadWinProc(void* param);

	ThreadWin(proc_type proc, void* param);
	~ThreadWin();

	//启动
	bool play();
	//暂停
	bool pause();
	//结束
	bool stop();
	//当前状态
	eState getState();

private:
	//禁止拷贝
	ThreadWin(const ThreadWin &) = delete;
	//禁止赋值
	ThreadWin& operator=(const ThreadWin &) = delete;

private:
	proc_type	m_proc;		//线程执行函数
	void*		m_param;	//执行函数参数
	eState		m_state;	//线程状态
	unsigned	m_handle;	//线程句柄
	unsigned	m_id;	 	//线程ID
};

.cpp

#include "ThreadWin.h"
#include <windows.h>
#include <process.h>

static unsigned __stdcall threadWinProc(void* param)
{
	ThreadWin* th = (ThreadWin*)param;

	while (ThreadWin::STOP != th->m_state)
	{
		th->m_proc(th->m_param);
	}

	return 0;
}

ThreadWin::ThreadWin(proc_type proc, void* param)
	: m_proc(proc)
	, m_param(param)
	, m_state(PAUSE)
{
	//err: 0
	m_handle = _beginthreadex(NULL, 0, threadWinProc, this, CREATE_SUSPENDED, &m_id);
}

ThreadWin::~ThreadWin()
{
	stop();
}

bool ThreadWin::play()
{
	if (0 == m_handle || STOP == m_state)
	{
		return false;
	}

	DWORD ret = ResumeThread((HANDLE)m_handle);
	if (-1 == ret)
	{
		return false;
	}

	m_state = PLAY;
	return true;
}

bool ThreadWin::pause()
{
	if (0 == m_handle || STOP == m_state)
	{
		return false;
	}

	if (PAUSE == m_state)
	{
		return true;
	}

	DWORD ret = SuspendThread((HANDLE)m_handle);
	if (-1 == ret)
	{
		return false;
	}

	m_state = PAUSE;
	return true;
}

bool ThreadWin::stop()
{
	if (0 == m_handle)
	{
		return false;
	}

	if (PAUSE == m_state)
	{
		bool ret = play();
		if (!ret)
		{
			return false;
		}
	}

	m_state = STOP;
	WaitForSingleObject((HANDLE)m_handle, INFINITE);
	CloseHandle((HANDLE)m_handle);
	m_handle = 0;

	return true;
}

ThreadWin::eState ThreadWin::getState()
{
	return m_state;
}

猜你喜欢

转载自blog.csdn.net/u013043408/article/details/83830598