经常看到有人找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,   
   &param,//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;    
}   

解决方案 »

  1.   

    void CThread::stop(unsigned   long   dwWait)   
    {   
        if(IsInvalid())   
            return;   
            
        ::WaitForSingleObject(m_hThreadHandle,  dwWait);    
        m_bStopFlag = true;       
    }   
    WaitForSingleObject没判断返回值
      

  2.   

    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帮助!!!!!
      

  3.   

    strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1));
    用法错误
      

  4.   

    m_nThreadID  = 0;
    不严谨,应该使用INVALID_HANDLE_VALUEMSDN没有明确说明 0 到底是不是有效ID
      

  5.   

    int             Run();  这个函数应该定义成virtual....
      

  6.   

    以前写的,估计还有问题,懒得去想了
    #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() {}};
      

  7.   


    #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;
    }
      

  8.   

    呵呵,谢谢楼上提了这么多意见。这是一个简单的模型。你说我这里的CThread::Resume 和 CThread::Suspend用法完全错误?
    不懂,哪里不对,你说一下吧?
      

  9.   


    strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1)); 用法错误???
    错在哪里?
      

  10.   


    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.原子数值置换什么时候能释放资源了?
      

  11.   

    strncpy(m_szThreadName, ThreadName, min(strlen(ThreadName), sizeof(m_szThreadName) - 1)); 1.直接使用,不用判断min。要判断min,不如用memcpy了。
    2.同时为了更好的支持UNICODE,对于字符串的长度计算最好用_countofstrncpy(m_szThreadName, ThreadName, sizeof(m_szThreadName) - 1); 
    不过对于底层来说使用ANSI也是可以的。呵呵~_tcsncpy(m_szThreadName, ThreadName, _countof(m_szThreadName) - 1); 
      

  12.   

    madmanahong 
    你提出的意见挺多,但是我看了,没有多少有价值的东西。
    钻牛角尖可能只是在闲极无聊的时候没事弄弄。
      

  13.   

    madmanahong 
    你提出的意见挺多,但是我看了,没有多少有价值的东西。
    钻牛角尖可能只是在闲极无聊的时候没事弄弄。
      

  14.   

    madmanahong 
    你提出的意见挺多,但是我看了,没有多少有价值的东西。
    钻牛角尖可能只是在闲极无聊的时候没事弄弄。
      

  15.   

    一直以为CSDN我的回复这么没有提交上来,这么一上来就是重复的3条???
    KAO
      

  16.   

    本来一件很简单的事,非要把它搞得那么复杂,
    还去研究什么“茴”字有几种写法
    只是提醒一下:
    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?就这些了,今天比较无聊,所以上来看了一下。