对于新手,编写线程,不知从何下手,不知编写线程要做那些,下面给出一个线程的简要框架
//////////////////////////////////////////////////////////////
//定义线程类YourThread.h #if !defined(YOURTHREAD_INCLUDE_FILE) #define YOURTHREAD_INCLUDE_FILE
class CYourThread :public CWinThread { .... DECLARE_DYNCREATE(CYourThread) public: CYourThread(); // protected constructor used by dynamic creation
// Attributes public: int m_bCloseFlag; HANDLE m_hEventKill; HANDLE m_hEventDead; //操件 public: void KillThread(); //清除本线程
protected: virtual void SingleStep(); virtual void Delete(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CEgClientCacheThread) public: virtual BOOL InitInstance(); virtual int ExitInstance(); virtual int Run(); //}}AFX_VIRTUAL // Implementation public: virtual ~CYourThread();
// Generated message map functions //{{AFX_MSG(CEgClientCacheThread) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG
DECLARE_MESSAGE_MAP() } #ednif
//////////////////////////////////////////// //实现文件YourThread.cpp #include "stdafx.h" #include "YourThread.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CYourThread, CWinThread) CYourThread::CYourThread() { m_bAutoDelete = FALSE; //注:该成员为CWinThread的成员,如为TRUE,在CWinThread::Delete()将删除线程 //置为FALSE不允许自动删除线程自已
m_hEventKill = CreateEvent(NULL, TRUE, FALSE, NULL); m_hEventDead = CreateEvent(NULL, TRUE, FALSE, NULL); }
CYourThread::~CYourThread() {
CloseHandle(m_hEventKill); CloseHandle(m_hEventDead); } BOOL cYourThread::InitInstance() { // TODO: perform and per-thread initialization here // avoid entering standard message loop by returning FALSE return TRUE; //用户接口线程,必须返回TRUE //如是 工作线程,代码如下 /* while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT) SingleStep(); // 避免进入标准消息循环,必须返回FALSE return FALSE; */ }
CYourThread:SingleStep() { //你的线程必一次执行的任务,每一次你的线程得到控制权,都会执行这个函数。 }
//如是用户接口线程,必须重载下面的函数 int CYourThread:Run { //注:正面的代码 除了加注中文解释的外,其他的与CWinThread::Run()是完全一致的 // for tracking the idle time state ASSERT_VALID(this);
// for tracking the idle time state BOOL bIdle = TRUE; LONG lIdleCount = 0;
// acquire and dispatch messages until a WM_QUIT message is received. for (;;) { SingleStep(); //执行本线程的单步函数 if(m_bCloseFlag ==TRUE) //指示线程关闭 { return ExitInstance(); } // phase2: pump messages while available //必须用下列方式进行消息循环,因为CAsyncSocket用了标准的Windows消息循环来处理数据发送和接收入 while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) //必须先用PeekMessage进行消息检查 { if(!(::GetMessage(&m_msgCur, NULL, NULL, NULL))) //取消息 return ExitInstance();
if (!PreTranslateMessage(&m_msgCur)) { ::TranslateMessage(&m_msgCur); ::DispatchMessage(&m_msgCur); }
if (IsIdleMessage(&m_msgCur)) { bIdle = TRUE; lIdleCount = 0; }
} } return ExitInstance();
}
int CYourThread::ExitInstance() { //如是用户接口线程,此处完成你的清除任务
VERIFY(SetEvent(m_hEventDead)); //这一句只有用户接口线程需要
return CWinThread::ExitInstance();
}
void CYourThread::Delete() { // calling the base here won't do anything but it is a good habit?????????????
//在CWinThread::Delete()如m_hAutoDelete为TRUE,则会删掉本进程 CWinThread::Delete();
// acknowledge receipt of kill notification VERIFY(SetEvent(m_hEventDead)); }
void CYourThread::KillThread() { // Note: this function is called in the context of other threads, // not the thread itself.
// reset the m_hEventKill which signals the thread to shutdown VERIFY(SetEvent(m_hEventKill));
// allow thread to run at higher priority during kill process SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL); WaitForSingleObject(m_hEventDead, INFINITE);
//下面两行只有工作线程才能要 /* WaitForSingleObject(m_hThread, INFINITE); delete this; */ } //////////////////////////////////////////////// //启动线程 void startYourThread() { CEgYourThread *pThread; if(!(pThread = (CYourThread*)AfxBeginThread(RUNTIME_CLASS(CYourThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED))) { AfxMessageBox(_T("创建线程失败")); return ; }
VERIFY(pThread->SetThreadPriority(THREAD_PRIORITY_IDLE)); //设置优先级 pEgThread->ResumeThread(); //启动线程 }
/////////////////////////////////////////////////////// //下面是解释 注意: 1 线程分两类: 工作线程 和 用户接口线程
2 用户接口线程可以进行有如键盘输入的用户交互,而工作线程则没有。当然正在消息处理机制上也有差异。 3 在线程初始化也不同. 如上面的例子 4 在重复使用的线程上,工作线程与用户接口线程的清除也不一样.
5 多线程时,必须解决资源冲突问题,刚开始学写线程时,可以用临界法来解决这个问题
在外部定义一个全局变量
CRITICAL_SECTION m_csYourThreadLock; //线程同步锁
在调用时初始化:
InitializeCriticalSection(&m_csYourThreadLock)
在退出所有线程后
DeleteCriticalSection(&m_csYourThreadLock)
在SingleStep()函数中,对共享资源的处理,加上这一临界锁
void CYourThread::SingleStep()
{
EnterCriticalSection(&m_csYourThreadLock);
// 共享资源处理代码
LeaveCriticalSection(&m_csYourThreadLock);
//其他代码
}

|