经常看到有人找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;
}
// 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;
}
解决方案 »
- 怎样判断一个文件的读写状态!菜鸟级问题!
- 控件如何阻止容器退出?
- 只要在头文件上加上#define UNICODE 就可以unicode 编码了吗?
- Com被编译后可代码与C++被编译后的代码有什么区别??
- 在技术内幕这本书里面的扩展名为ogx为组件?怎么用?
- 关于在DLL中使用COM组件的问题
- 请问使用vc6.0在windows98下写的程序在window2000和windowxp下可以运行吗
- 求救!
- 前辈们,有没有<<消息大全>>之类的东东?
- 急!请教CustomAppWizard的问题!
- 为什么会error LNK2019: 无法解析的外部符号
- 用ATL写一个客户端的登陆程序应该怎么入手啊?
{
if(IsInvalid())
return;
::WaitForSingleObject(m_hThreadHandle, dwWait);
m_bStopFlag = true;
}
WaitForSingleObject没判断返回值
{
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帮助!!!!!
用法错误
不严谨,应该使用INVALID_HANDLE_VALUEMSDN没有明确说明 0 到底是不是有效ID
#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() {}};
#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;
}
不懂,哪里不对,你说一下吧?
strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1)); 用法错误???
错在哪里?
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.原子数值置换什么时候能释放资源了?
2.同时为了更好的支持UNICODE,对于字符串的长度计算最好用_countofstrncpy(m_szThreadName, ThreadName, sizeof(m_szThreadName) - 1);
不过对于底层来说使用ANSI也是可以的。呵呵~_tcsncpy(m_szThreadName, ThreadName, _countof(m_szThreadName) - 1);
你提出的意见挺多,但是我看了,没有多少有价值的东西。
钻牛角尖可能只是在闲极无聊的时候没事弄弄。
你提出的意见挺多,但是我看了,没有多少有价值的东西。
钻牛角尖可能只是在闲极无聊的时候没事弄弄。
你提出的意见挺多,但是我看了,没有多少有价值的东西。
钻牛角尖可能只是在闲极无聊的时候没事弄弄。
KAO
还去研究什么“茴”字有几种写法
只是提醒一下:
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?就这些了,今天比较无聊,所以上来看了一下。