本⽂实例讲述了VC中CWinThread类以及和createthread API的区别分析,分享给⼤家供⼤家参考。具体分析如下:CWinThreadCObject
└CCmdTarget └CWinThread
CWinThread对象代表在⼀个应⽤程序内运⾏的线程。运⾏的主线程通常由CWinApp的派⽣类提供;CWinApp由CWinThread派⽣。另外,CWinThread对象允许⼀给定的应⽤程序拥有多个线程。
CWinThread⽀持两种线程类型:⼯作者线程(Worker Thread)和⽤户界⾯线程(UI thread)。⼯作者线程没有收发消息的功能(没有消息队列):例如,在电⼦表格应⽤程序中进⾏后台计算的线程。
⽤户界⾯线程具有收发消息的功能,并处理从系统收到的消息。CWinApp及其派⽣类是⽤户界⾯线程的例⼦。其它⽤户界⾯线程也可由CWinThread直接派⽣。
CWinThread类的对象存在于线程的⽣存期。如果你希望改变这个特性,将m_bAutoDelete设为FALSE。
要使你的代码和MFC是完全线程安全的,CWinThread类是完全必要的。框架使⽤的⽤来维护与线程相关的信息的线程局部数据由CWinThread对象管理。由于依赖CWinThread来处理线程局部数据(Thread Local Storage),任何使⽤MFC的线程必须由MFC创建。例如,由运⾏时函数_beginthreadex创建的线程不能使⽤任何MFC API。
为了创建⼀个线程,调⽤AfxBeginThread函数。根据你需要⼯作者线程还是⽤户界⾯线程,有两种调⽤AfxBeginThread的格式。如果你需要⽤户界⾯线程,则将指向你的CWinThread派⽣类的CRuntimeClass的指针传递给AfxBeginThread。如果你需要创建⼯作者线程,则将指向控制函数的指针和控制函数的参数传递给AfxBeginThread。对于⼯作者线程和⽤户界⾯线程,你可以指定可选的参数来修改优先级,堆栈⼤⼩,创建标志和安全属性。
AfxBeginThread线程将返回指向新的CWinThread对象的指针。
与调⽤AfxBeginThread相反,你可以构造⼀个CWinThread派⽣类的对象,然后调⽤CreateThread。如果你需要在连续创建和终⽌线程的执⾏之间重复使⽤CWinThread对象,这种两步构造⽅法⾮常有⽤。CWinThread类成员数据成员
m_bAutoDelete 指定线程结束时是否要销毁对象 m_hThread 当前线程的句柄 m_nThreadID 当前线程的ID
m_pMainWnd 保存指向应⽤程序的主窗⼝的指针
m_pActiveWnd 指向容器应⽤程序的主窗⼝,当⼀个OLE服务器被现场激活时 构造函数
CWinThread 构造⼀个CWinThread对象
CreateThread 开始⼀个CWinThread对象的执⾏ 操作
GetMainWnd 查询指向线程主窗⼝的指针 GetThreadPriority 获取当前线程的优先级
PostThreadMessage 向另外的CWinThread对象传递⼀条消息 ResumeThread 减少⼀个线程的挂起计数 SetThreadPriority 设置当前线程的优先级 SuspendThread 增加⼀个线程的挂起计数 可重载函数
ExitInstance 重载以进⾏线程终⽌时的清理⼯作 InitInstance 重载以实现线程实例的初始化 OnIdle 重载以进⾏线程特定的空闲操作
PreTranslateMessage 在消息被发送到Windows函数TranslateMessage和DispatchMessage之前过滤消息 IsIdleMessage 检测特定的消息
ProcessWndProcException 截获线程消息和命令处理函数出现的所有未处理的异常 ProcessMessageFilter 在特定的消息到达应⽤程序之前截获消息
Run 线程的具有消息收发功能的控制函数,可重载以定制缺省的消息循环 AfxBeginThread和CreateThread具体区别
具体说来,CreateThread这个 函数是windows提供给⽤户的 API函数,是SDK的标准形式.AfxBeginThread,是编译器对原来的CreateThread函数的封装,⽤与MFC.⽽_beginthread是C的运⾏库函数。
在使⽤AfxBeginThread时,线程函数的定义为:UINT _yourThreadFun(LPVOID pParam)
在使⽤CreateThread时,线程的函数定义为: DWORD WINAPI _yourThreadFun(LPVOID pParameter)。
两个的实质都是⼀样的,不过AfxBeginThread返回⼀个CWinThread的指针,就是说他会new⼀个CWinThread对象,⽽且这个对象是⾃动删除的(在线程运⾏结束时),给我们带来的不便就是⽆法获得它的状态,因为随时都有可能这个指针指向的是⼀个已经⽆效的内存区域,所以使⽤时(如果需要了解它的运⾏状况的话)⾸先CREATE_SUSPENDED让他挂起,然后m_bAutoDelete=FALSE,接着才ResumeThread,最后不要了delete那个指针。
CreatThread就⽅便多了,它返回的是⼀个句柄,如果你不使⽤CloseHandle的话就可以通过他安全的了解线程状态,最后不要的时候CloseHandle,Windows才会释放资源(线程内核对象).下⾯我们就来看⼀下AfxBeginThread函数的内部实现:
复制代码 代码如下://启动worker线程
CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs){
ASSERT(pfnThreadProc != NULL);
CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam); ASSERT_VALID(pThread);
if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize, lpSecurityAttrs)) {
pThread->Delete(); return NULL; }
VERIFY(pThread->SetThreadPriority(nPriority)); if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1); return pThread;}
//启动UI线程
CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass,int nPriority, UINT nStackSize, DWORDdwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs){
ASSERT(pThreadClass != NULL);
ASSERT(pThreadClass->IsDerivedFrom(RUNTIME_CLASS(CWinThread))); CWinThread* pThread = (CWinThread*)pThreadClass->CreateObject(); if (pThread == NULL)
AfxThrowMemoryException(); ASSERT_VALID(pThread);
pThread->m_pThreadParams = NULL;
if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize, lpSecurityAttrs)) {
pThread->Delete(); return NULL; }
VERIFY(pThread->SetThreadPriority(nPriority));
if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1); return pThread;}
主要创建函数是
复制代码 代码如下:
pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,lpSecurityAttrs))也就是
复制代码 代码如下:
CWinThread::CreateThread。
希望本⽂所述对⼤家的VC程序设计有所帮助。
因篇幅问题不能全部显示,请点此查看更多更全内容