基于MFC的编写线程快速入门
基于MFC的编写线程快速入门
程序员之家 作者:不详 日期:2003-2-1 19:19:00
--------------------------------------------------------------------------------
对于新手,编写线程,不知从何下手,不知编写线程要做那些,下面给出一个线程的简要框架
//////////////////////////////////////////////////////////////
//定义线程类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);
//其他代码
}