【源码】:放源码了,线程类!

djfu 2008-05-27 11:54:09
经常看到有人找CThread类源码,自己修改了一个。


// HEADER FILE : thread.h
// Thread.h: interface for the CThread class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_THREAD_H__07971CDB_D943_4826_903B_1BA1FF7634A6__INCLUDED_)
#define AFX_THREAD_H__07971CDB_D943_4826_903B_1BA1FF7634A6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afxmt.h>
#include <windows.h>

typedef unsigned (WINAPI* THREAD_FUNC)(void *ThreadParam);

class CThread;
typedef struct tagThreadParam
{
CThread *pThread;
void *pParam;
} tThreadParam ;

class CThread
{
public:
CThread(THREAD_FUNC ThreadFunc, void *ThreadParam = NULL, bool bCreateSuspended = false, SECURITY_ATTRIBUTES* pSecurityAttributes = NULL, const char* ThreadName = NULL);
virtual ~CThread() { stop(100); }

int Start();
int Suspend();
int Resume();
void stop(unsigned long dwWait = INFINITE);
int Run();

HANDLE GetThreadHandle() const { return m_hThreadHandle; }
long GetThreadID() const { return m_nThreadID; }
operator HANDLE() const { return m_hThreadHandle; };
const char* GetThreadName() const { return (const char *)m_szThreadName; }

bool IsInvalid() const { return m_hThreadHandle <= 0 ? true : false; };
bool IsSuspended() const { return m_bSuspend; };
bool IsStopped() const { return m_bStopFlag; };
bool IsRunning();

private:
CThread(const CThread& ) {}
CThread& operator=( const CThread& ) {}

private:
bool m_bSuspend;
HANDLE m_hThreadHandle;
unsigned int m_nThreadID;
char m_szThreadName[512];
bool m_bStopFlag;
SECURITY_ATTRIBUTES*p_Attr;
THREAD_FUNC m_ThreadFunc;
void *m_pInputParam;
};

static unsigned WINAPI thread_function(void* pArg)
{
return ((CThread*)pArg)->Run();
}

#endif // !defined(AFX_THREAD_H__07971CDB_D943_4826_903B_1BA1FF7634A6__INCLUDED_)






// CPP FILE: thread.cpp
// Thread.cpp: implementation of the CThread class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "Thread.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


#include "thread.h"
#include <process.h>


CThread::CThread(THREAD_FUNC ThreadFunc, void *ThreadParam, bool bCreateSuspended, SECURITY_ATTRIBUTES* pSecurityAttributes, const char* ThreadName):
p_Attr(pSecurityAttributes), m_hThreadHandle(0)
{
m_bStopFlag = false;
m_bSuspend = bCreateSuspended;
m_nThreadID = 0;
memset(m_szThreadName, 0, sizeof(m_szThreadName));
strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1));
m_ThreadFunc = ThreadFunc;
m_pInputParam = ThreadParam;
}

int CThread::Start()
{
tThreadParam param;
param.pParam = m_pInputParam;
param.pThread = this;
BOOL bRet = _beginthreadex(
p_Attr,
0,
m_ThreadFunc,//thread_function,
¶m,//this,
(m_bSuspend ? CREATE_SUSPENDED : 0 ),
&m_nThreadID);

m_hThreadHandle = (HANDLE)bRet;
m_ThreadFunc = thread_function;

return bRet;
}

// simulate to realize it
int CThread::Run()
{
while(!IsStopped())
{
int sum = 0;
for(int i = 0; i < 100; i ++)
{
sum += i;
}
printf("%d\n", sum);
Sleep(100);
}

_endthreadex(EXIT_SUCCESS);

return 0;
}

void CThread::stop(unsigned long dwWait)
{
if(IsInvalid())
return;

::WaitForSingleObject(m_hThreadHandle, dwWait);
m_bStopFlag = true;
}


int CThread::Suspend()
{
if(IsInvalid())
{
return -2;
}

if(::SuspendThread(m_hThreadHandle) == -1)
{
return -1;
}

m_bSuspend = true;
return 0;
}

int CThread::Resume()
{
if(IsInvalid())
{
return -2;
}

if(::ResumeThread(m_hThreadHandle) == -1)
{
return -1;
}

m_bSuspend = false;
return 0;
}


bool CThread::IsRunning()
{
if(IsInvalid())
return false;

if(m_bSuspend)
return false;

if(::WaitForSingleObject(m_hThreadHandle, 0) == WAIT_TIMEOUT)
return true;
else
return false;
}


...全文
222 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
djfu 2008-10-18
  • 打赏
  • 举报
回复
本来一件很简单的事,非要把它搞得那么复杂,
还去研究什么“茴”字有几种写法。。。


只是提醒一下:
1) TerminateThread 是线程异常中止,不给线程任何清除退出现场的机会,在正常的程序中是不允许出现的。
2) _beginthreadex 是要和 _endthreadex 成对出现的
3) strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1));
有没有考虑过如果 ThreadName 的长度大过 m_szThreadName的情况?
4) 是否自删除,这么复杂的设计有必要吗?吓唬刚入门的新手程序员用的吧?
5) ResumeThread和SuspendThread我没看到有丝毫的错误,难道你自己写了一个MSDN?

就这些了,今天比较无聊,所以上来看了一下。
djfu 2008-10-18
  • 打赏
  • 举报
回复
一直以为CSDN我的回复这么没有提交上来,这么一上来就是重复的3条???
KAO
djfu 2008-10-18
  • 打赏
  • 举报
回复
madmanahong
你提出的意见挺多,但是我看了,没有多少有价值的东西。
钻牛角尖可能只是在闲极无聊的时候没事弄弄。
djfu 2008-10-18
  • 打赏
  • 举报
回复
madmanahong
你提出的意见挺多,但是我看了,没有多少有价值的东西。
钻牛角尖可能只是在闲极无聊的时候没事弄弄。
djfu 2008-10-18
  • 打赏
  • 举报
回复
madmanahong
你提出的意见挺多,但是我看了,没有多少有价值的东西。
钻牛角尖可能只是在闲极无聊的时候没事弄弄。
madmanahong 2008-10-09
  • 打赏
  • 举报
回复
strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1));

1.直接使用,不用判断min。要判断min,不如用memcpy了。
2.同时为了更好的支持UNICODE,对于字符串的长度计算最好用_countof

strncpy(m_szThreadName, ThreadName, sizeof(m_szThreadName) - 1);


不过对于底层来说使用ANSI也是可以的。呵呵~

_tcsncpy(m_szThreadName, ThreadName, _countof(m_szThreadName) - 1);
deh_1984 2008-05-30
  • 打赏
  • 举报
回复
mark
stivenjia 2008-05-29
  • 打赏
  • 举报
回复

DWORD IsThreadRunning(HANDLE hThread,BOOL &bRunning)
{
DWORD dwRet = 0;
if(GetExitCodeThread(hThread,&dwRet))
{
if(dwRet == STILL_ACTIVE)
bRunning = TRUE;
else
bRunning = FALSE;
return 0;
}
return GetLastError();
}

这仅仅是一个地方其他的地方懒得改
1.线程结束难道线程内分配资源不需要释放?
2.原子数值置换什么时候能释放资源了?
goingup 2008-05-29
  • 打赏
  • 举报
回复
MARK
madmanahong 2008-05-28
  • 打赏
  • 举报
回复
给分告诉你
madmanahong 2008-05-27
  • 打赏
  • 举报
回复

#include "stdafx.h"
#include "thread.h"
#include <process.h>

//namespace {
// static UINT WINAPI ThreadProc(LPVOID param)
// {
// CThread* thread = reinterpret_cast<CThread*>(param);
// return thread->execute();
// }
//};


CThread::CThread(bool self_delete)
: thread_handle_(INVALID_HANDLE_VALUE)
, thread_id_(0)
, suspended_(false)
, terminated_(false)
, self_delete_(self_delete)
{
memset(thread_info_, 0, sizeof(thread_info_));
}

CThread::~CThread()
{
/* 结束时要停止线程 */
HANDLE h = (HANDLE)::InterlockedExchange((PLONG)&thread_handle_, (LONG)INVALID_HANDLE_VALUE);
if (h!=INVALID_HANDLE_VALUE) {
if (WAIT_OBJECT_0!=::WaitForSingleObject(h, 0)) {
::TerminateThread(h, -8008);
}
}
thread_id_ = 0;
}

DWORD CThread::wait_for(DWORD ms)
{
return ::WaitForSingleObject(thread_handle_, ms);
}

bool CThread::start_thread(bool suspended)
{
on_init();

/* 开启线程 */
assert(thread_handle_==INVALID_HANDLE_VALUE);
suspended = suspended;
thread_handle_ = (HANDLE)_beginthreadex(
NULL,
0,
ThreadProc,
(void*)this,
suspended ? CREATE_SUSPENDED : 0,
&thread_id_
);

if (thread_handle_==INVALID_HANDLE_VALUE)
return FALSE;

on_start();

return TRUE;
}

bool CThread::stop_thread(DWORD ms)
{
/* 不能蛇咬尾巴 */
assert(::GetCurrentThreadId()!=thread_id_);

/* 首先要进行停止操作,否则resume之后,线程得到时间,就又被suspend了! */
terminated_ = true;

/* 停止之前先恢复一下 */
resume_thread();

/* 每次stop一次即可 */
HANDLE h = (HANDLE)::InterlockedExchange((PLONG)&thread_handle_, (LONG)INVALID_HANDLE_VALUE);
if (h==INVALID_HANDLE_VALUE) {
LOG__("[message] close thread but handle invalid.");
return false;
}

/* 注意如果外界调用stop的话,自动取消self_delete模式,否则内存冲突 */
self_delete_ = false;

if (WAIT_OBJECT_0!=::WaitForSingleObject(h, ms)) {
/* 线程没有结束,那么就等待 */
on_stop(true);
::TerminateThread(h, -8888);
} else {
on_stop(false);
}

/* 清除相关数据 */
thread_id_ = 0;
memset(thread_info_, 0, sizeof(thread_info_));

CloseHandle(h);
return true;
}

DWORD CThread::suspend_thread()
{
return SuspendThread(thread_handle_);
}

DWORD CThread::resume_thread(bool all)
{
/* 注意线程唤醒这些是需要计数器的 */
DWORD ticks = -1;
for (;;) {
ticks = ResumeThread(thread_handle_);
if (ticks==-1)
break;

if (!all)
break;

if (ticks>0)
continue;
else
break;
}
return ticks;
}

bool CThread::is_valid()
{
return (thread_handle_==INVALID_HANDLE_VALUE) ? FALSE : TRUE;
}


/* 得到线程句柄 */
HANDLE CThread::get_handle()
{
return thread_handle_;
}

/* 得到线程编号 */
DWORD CThread::get_threadid()
{
return thread_id_;
}


void CThread::set_threadinfo(LPCTSTR info)
{
_tcsncpy(thread_info_, info, sizeof(thread_info_)-1);
}

LPCTSTR CThread::get_threadinfo()
{
return thread_info_;
}

void CThread::set_autodelete(bool del)
{
self_delete_ = del;
}

bool CThread::get_autodelete()
{
return self_delete_;
}

void CThread::set_terminate()
{
terminated_ = true;
}

UINT CThread::execute()
{
// 一个线程的意外不应该影响整个进程,所以这里try住了
int retcode = 0;

/////////////////////////////////////////////////////
MY_TRY_BEGIN

retcode = on_execute();

MY_CATCH_ALL

retcode = 8005;
on_exception();

MY_CATCH_END
/////////////////////////////////////////////////////

/* 线程运行完毕 */
on_runover();

/* 清除自己的内存 */
HANDLE h = (HANDLE)::InterlockedExchange((PLONG)&thread_handle_, (LONG)INVALID_HANDLE_VALUE);
if (h!=INVALID_HANDLE_VALUE) {
memset(thread_info_, 0, sizeof(thread_info_));
::CloseHandle(h);

/* 如果线程是自删除的,删除自己 */
if (self_delete_) {
delete this;
}
}

return retcode;
}

UINT CThread::on_execute()
{
return -8806;
}

madmanahong 2008-05-27
  • 打赏
  • 举报
回复
以前写的,估计还有问题,懒得去想了。。。


#pragma once

//
// 封装了windows线程,使用的时候请派生,并不同于MFC的CWinThread
// 注意delete一个线程指针的时候,最慢需要1秒钟。所以需要注意用户等待问题
//
//

class CThread
{
protected:
HANDLE thread_handle_; // 线程句柄
unsigned int thread_id_; // 线程号
bool suspended_; // 标志是否已挂起
bool terminated_; // 标志是否已终止
bool self_delete_; // 是否自己删除
TCHAR thread_info_[128]; // 一个线程保存信息

public:
// 线程是否自删除,默认关闭,否则不容易管理
CThread(bool self_delete = false);
virtual ~CThread();

public:
/* 启动线程 */
bool start_thread(bool suspended = false);

/* 终止线程 */
bool stop_thread(DWORD ms = 1000);

/* 等待线程 */
DWORD wait_for(DWORD ms = -1);

/* 挂起线程 */
DWORD suspend_thread();

/* 唤醒线程 */
DWORD resume_thread(bool all = true);

public:
/* 判断线程是否有效 */
bool is_valid();

/* 得到线程句柄 */
HANDLE get_handle();

/* 得到线程编号 */
DWORD get_threadid();

/* 设置得到线程信息,最大为128字节 */
void set_threadinfo(LPCTSTR info);
LPCTSTR get_threadinfo();

/* 设置为自动删除 */
void set_autodelete(bool del);

/* 返回是否自动删除 */
bool get_autodelete();

/* 设置线程退出标志 */
void set_terminate();

protected:
static UINT WINAPI ThreadProc(LPVOID param)
{
CThread* thread = reinterpret_cast<CThread*>(param);
return thread->execute();
}

/* 线程人口 */
UINT execute();

/* 线程的主运行体 */
virtual UINT on_execute() = 0;

/* 线程开始事件,还没有完全开始 */
virtual void on_init() {}

/* 线程已经创建,但是不保证启动 */
virtual void on_start() {}

/* 线程停止事件,term为是否强行中止! */
virtual void on_stop(bool term) {}

/* 线程正常结束,即线程体执行完毕 */
virtual void on_runover() {}

/* 异常事件,发生异常之后调用 */
virtual void on_exception() {}

};



madmanahong 2008-05-27
  • 打赏
  • 举报
回复
int Run();

这个函数应该定义成virtual....

madmanahong 2008-05-27
  • 打赏
  • 举报
回复
m_nThreadID = 0;


不严谨,应该使用INVALID_HANDLE_VALUE

MSDN没有明确说明 0 到底是不是有效ID
madmanahong 2008-05-27
  • 打赏
  • 举报
回复
strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1));


用法错误。。。
madmanahong 2008-05-27
  • 打赏
  • 举报
回复
int CThread::Suspend()
{
if(IsInvalid())
{
return -2;
}

if(::SuspendThread(m_hThreadHandle) == -1)
{
return -1;
}

m_bSuspend = true;
return 0;
}

int CThread::Resume()
{
if(IsInvalid())
{
return -2;
}

if(::ResumeThread(m_hThreadHandle) == -1)
{
return -1;
}

m_bSuspend = false;
return 0;
}


这两个函数实现完全错误。


再去看看MSDN帮助!!!!!
madmanahong 2008-05-27
  • 打赏
  • 举报
回复
void CThread::stop(unsigned long dwWait)
{
if(IsInvalid())
return;

::WaitForSingleObject(m_hThreadHandle, dwWait);
m_bStopFlag = true;
}


WaitForSingleObject没判断返回值

madmanahong 2008-05-27
  • 打赏
  • 举报
回复
m_hThreadHandle
没closehandle()
djfu 2008-05-27
  • 打赏
  • 举报
回复

strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1));



用法错误???
错在哪里?
djfu 2008-05-27
  • 打赏
  • 举报
回复
呵呵,谢谢楼上提了这么多意见。

这是一个简单的模型。

你说我这里的CThread::Resume 和 CThread::Suspend用法完全错误?
不懂,哪里不对,你说一下吧?

15,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧