本文共 3892 字,大约阅读时间需要 12 分钟。
在开发多线程程序时,常常碰到线程管理的问题。当有多种线程的时候,为了控制每个线程,编程工作也变得复杂。事实上,我们对线程的控制大多是相似的,所以把这些控制抽象出来,形成一个可复用的程序模块,将能大大提高开发效率和代码质量。 首先我们对线程的使用目的进行分析和归纳。一般来说,有如下几种: 1) 独立线程。执行一项在后台完成的工作,工作频率很低,线程的生命期里只完成一项任务。线程基本上不需要什么管理。 2) 定时线程。线程每隔一段时间,定时执行一定的功能,可能是查看某一状态,或输出某种信息。线程要设定时间间隔,并且需要显式地中止才会结束。 3) 守护线程。线程等待某事的发生,当事件发生时开始工作,完成后继续进行等待状态。因为事件发生的非常频繁时,使用守护线程以避免独立线程会带来的太多的线程开销。线程要能随时启动,也需要显式地中止才会结束。 1) 等待。当工作完成时,自动进入等待状态,而不是中止。 设计一个具有以上管理功能的线程并不困难,但为每一个线程都写一段这样的代码就显得很麻烦了,更何况这些代码其实都是类似的。为此,笔者设计了一个线程管理类,把线程的工作函数放入线程管理的框架内执行。线程的工作函数不再是线程的开始入口,而仅被作为一个函数被调用。 class CThreadMaster{ public : CThreadMaster( void ); ~ CThreadMaster( void ); typedef void ( * WorkFuncType)( void * param); enum CycleTimeEnum{ AlwaysWait = - 1 , AlwaysWork = 0 }; void Start(); void Stop(); void WorkNow(); void Set(WorkFuncType function, void * parameter, int cycleTime); void SetWorkFunction( WorkFuncType function ); void SetWorkParameter( void * parameter); void SetCycleTime( int cycleTime ); unsigned long GetThreadId(); static unsigned __stdcall WorkThread( void * lpParameter ); protected : enum ThreadCmd{ nothing = 0 , stop}; ThreadCmd m_ThreadCmd; HANDLE m_hThread; HANDLE m_hEvent; unsigned int m_ThreadId; int m_CycleTime; void * m_lpParameter; WorkFuncType m_WorkFunction; }; 函数void Set(WorkFuncType function, void * parameter, int cycleTime);用来设置线程的工作函数、工作参数、和工作周期,参数如下: cycleTime:工作函数的执行周期期,可以是一个正整数的时间值,单位为1/1000秒,也可以是如CycleTimeEnum定义的两个特殊值: enum CycleTimeEnum{ AlwaysWait = -1, AlwaysWork = 0}; cycleTime的值为AlwaysWait表示执行完工作函数以后,线程一直等待,直到WorkNow函数被调用,或线程被Stop函数中止; cycleTime的值为AlwaysWork表示不停地循环调用工作函数。 如果cycleTime为其它正值,那么执行完工作函数之后,等待cycleTime指定的时长并重新调用工作函数。如果在等待期间调用了WorkNow,那么工作函数将立刻被执行。 函数Start()、Stop()用来启动的中止线程,WorkNow()用来使线程进入工作状态,多次调用WorkNow不会影响工作状态。 使用这个类,我们只要把线程函数定义为WorkFuncType类 型的静态函数,然后调用CThreadMaster类实例的Set函数设置该函数的指针、参数、和工作状态,就可以使用CThreadMaster提供的 控制函数来管理线程了。线程所有的工作都会安全地开始,并优雅地结束。CThreadMaster实例销毁时,也会自动结束线程。 现把这个类的实现代码放到下面,以供参考, CThreadMaster.cpp: #include <process.h>#include ". hreadmaster.h" CThreadMaster::CThreadMaster(void)...{ m_ThreadCmd = nothing; m_hThread = NULL; m_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); m_ThreadId = 0; m_CycleTime = AlwaysWork; m_WorkFunction = NULL; m_lpParameter = NULL;} CThreadMaster::~CThreadMaster(void)...{ Stop(); CloseHandle(m_hEvent);} void CThreadMaster::Start()...{ if (m_ThreadId!=0) return; m_ThreadCmd = nothing; m_hThread = (HANDLE)_beginthreadex(NULL,0, WorkThread, (void *)this, 0, &m_ThreadId);} void CThreadMaster::Stop()...{ if (m_ThreadId==0) return; m_ThreadCmd = stop; WorkNow(); WaitForSingleObject(m_hThread, INFINITE); m_ThreadCmd = nothing; m_ThreadId = 0; m_hThread = NULL;} void CThreadMaster::WorkNow()...{ if (m_hThread==0) ...{ Start(); SetEvent(m_hEvent); }else SetEvent(m_hEvent);} unsigned CThreadMaster::WorkThread( void * lpParameter )...{ CThreadMaster * pThis = (CThreadMaster*) lpParameter; if (pThis==NULL) return -1; for(;;) ...{ if (pThis->m_CycleTime > AlwaysWork) WaitForSingleObject(pThis->m_hEvent, pThis->m_CycleTime); else if (pThis->m_CycleTime<=AlwaysWait) WaitForSingleObject(pThis->m_hEvent, INFINITE); if (pThis->m_ThreadCmd==stop) return 0; if (pThis->m_WorkFunction!=NULL) ...{ try...{ (*pThis->m_WorkFunction)(pThis->m_lpParameter); }catch (...)...{ } } } return -2;} void CThreadMaster::Set(WorkFuncType function, void * parameter, int cycleTime)...{ m_WorkFunction = function; m_lpParameter = parameter; m_CycleTime = cycleTime;} void CThreadMaster::SetWorkFunction( WorkFuncType function )...{ m_WorkFunction = function;} void CThreadMaster::SetWorkParameter( void * parameter)...{ m_lpParameter = parameter;} void CThreadMaster::SetCycleTime( int cycleTime )...{ m_CycleTime = cycleTime;} unsigned long CThreadMaster::GetThreadId()...{ return m_ThreadId;}
转载地址:http://escdi.baihongyu.com/