CWinThread的使用方法.docx
《CWinThread的使用方法.docx》由会员分享,可在线阅读,更多相关《CWinThread的使用方法.docx(14页珍藏版)》请在冰豆网上搜索。
![CWinThread的使用方法.docx](https://file1.bdocx.com/fileroot1/2022-12/12/1f08a5c0-145e-473d-8363-9c3d046320b2/1f08a5c0-145e-473d-8363-9c3d046320b21.gif)
CWinThread的使用方法
1.AfxBeginThread与CWinThread:
:
CreateThread的区别:
2.常见的启动线程函数有三个:
CreateThread(), _beginThread(以及_beginThreadEx()),AfxBeginThread()
1和2是sdk函数,3是mfc函数
至于启动的是工作者线程还是UI线程,是由函数3的参数来决定的;
创建用户界面线程的步骤:
使用ClassWizard创建类CWinThread的派生类(以CUIThread类为例)classCUIThread:
publicCWinThread
{
DECLARE_DYNCREATE(CUIThread)
protected:
CUIThread(); //protectedconstructorusedbydynamiccreation
//Attributes
public:
//Operations
public:
//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CUIThread)
public:
virtualBOOLInitInstance();
virtualintExitInstance();
//}}AFX_VIRTUAL
//Implementation
protected:
virtual~CUIThread();
//Generatedmessagemapfunctions
//{{AFX_MSG(CUIThread)
//NOTE-theClassWizardwilladdandremovememberfunctionshere.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
重载函数InitInstance()和ExitInstance()。
BOOLCUIThread:
:
InitInstance()
{
CFrameWnd*wnd=newCFrameWnd;
wnd->Create(NULL,"UIThreadWindow");
wnd->ShowWindow(SW_SHOW);
wnd->UpdateWindow();
m_pMainWnd=wnd;
returnTRUE;
}
创建新的用户界面线程voidCUIThreadDlg:
:
OnButton1()
{
CUIThread*pThread=newCUIThread();
pThread->CreateThread();
}
请注意以下两点:
A、在UIThreadDlg.cpp的开头加入语句:
#include"UIThread.h"
B、把UIThread.h中类CUIThread()的构造函数的特性由protected改为public。
用户界面线程的执行次序与应用程序主线程相同,首先调用用户界面线程类的InitInstance()函数,如果返回TRUE,继续调用线程的Run()函数,该函数的作用是运行一个标准的消息循环,并且当收到WM_QUIT消息后中断,在消息循环过程中,Run()函数检测到线程空闲时(没有消息),也将调用OnIdle()函数,最后Run()函数返回,MFC调用ExitInstance()函数清理资源。
你可以创建一个没有界面而有消息循环的线程,例如:
你可以从CWinThread派生一个新类,在InitInstance函数中完成某项任务并返回FALSE,这表示仅执行InitInstance函数中的任务而不执行消息循环,你可以通过这种方法,完成一个工作者线程的功能。
文章出处:
CWinThread的使用方法
技术资料 2011-01-1216:
44:
52 阅读215 评论0 字号:
大中小 订阅
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线程的具有消息收发功能的控制函数,可重载以定制缺省的消息循环
第一创建线程
函数原型:
CWinThread*AfxBeginThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam,intnPriority=
THREAD_PRIORITY_NORMAL,UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTES
lpSecurityAttrs=NULL);
CWinThread*AfxBeginThread(CRuntimeClass*pThreadClass,intnPriority=THREAD_PRIORITY_NORMAL,
UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL);
返回值:
指向新创建的线程对象。
参数:
pfnThreadProc:
工作线程的函数指针,不可以为空。
并且工作线程的函数必须如此声明:
UINTMyControllingFunction(LPVOIDpParam);
pThreadClass:
从CWinThread类继承来的对象的RUNTIME_CLASS指针。
pParam:
传递给工作线程函数pfnThreadProc的参数。
nPriority:
线程的优先级。
如果为0,则与创建它的线程优先级相同。
可以通过参考Win32Programmer’s
Reference中的SetThreadPriority得到所有可用的优先级列表和描述。
nStackSize:
以字节为单位指定新线程的堆栈大小。
如果为0,则与创建它的线程的堆栈大小相同。
dwCreateFlags:
指定一个额外的标志控制线程的产生。
它可以包括下面两个值中的一个:
CREATE_SUSPENDED:
以挂起模式开始线程,并且指定挂起次数.当调用ResumeThread时,这个
线程才会被执行。
0 :
创建之后,马上执行线程。
lpSecurityAttrs:
指向SECURITY_ATTRIBUTES结构的指针,结构中指定了线程的安全属性。
如果为NULL,则与
创建它的线程的安全属性相同。
如果希望得到更多的有关SECURITY_ATTRIBUTES结构的信息,
请参考Win32Programmer’sReference。
注释:
调用这个函数创建一个新的线程。
第一种形式的AfxBeginThread创建一个工作线程;第二种形式创建一个用户
接口线程。
AfxBeginThread创建一个新CWinThread对象,调用它的CreateThread函数开始执行线程并且返回指向线程的指
针。
Checksaremadethroughouttheproceduretomakesureallobjectsaredeallocatedproperly
shouldanypartofthecreationfail.终止线程,可以在线程函数中调用AfxEndThread,或者从工作线程
的函数中返回。
示例:
创建一个工作线程:
UINT WorkForce(LPVOIDlpParameter);//线程函数声明
CWinThread *pMyFirstWorker,*pMySecondWorker;
LPVOID pParam=NULL;
int nPriority=THREAD_PRIORITY_ABOVE_NORMAL;//默认为THREAD_PRIORITY_NORMAL
UINT nStackSize=0;//与创建它的线程堆栈大小相同
DWORD dwCreateFlags=0;//创建后立即执行
LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL;//与创建它的线程安全属性相同
pMyFirstWorker=AfxBeginThread(WorkForce,pParam,nPriority,nStackSize,
dwCreateFlags,lpSecurityAttrs);
pMySecondWorker=AfxBeginThread(WorkForce,(LPVOID)&port);//如果采用默认值
UINT WorkForce(LPVOIDlpParameter //线程所需参数,可以通过它传递数据)
{
intnPort=*((int*)pParam);//这里获得的nPort就是输入时候传递进来的.
return0;//什么不做
}
第二销毁线程
首先需要说明的是销毁线程函数AfxEndThread,只能运用于线程内销毁.不同线程之间应建立通信渠道.下面是段具体代码:
UINT WorkForce(LPVOIDlpParameter //线程所需参数,可以通过它传递数据)
{
intnPort=*((int*)pParam);//这里获得的nPort就是输入时候传递进来的.
if(bExitCode)//满足销毁的条件
{
DWORDExitCode=0;
GetExitCodeThread(p->m_hThread,&ExitCode);
//p为需要销毁的CWindThreadZ指针,其在创建线程时可以拿到.
if(ExitCode>0)
AfxEndThread(ExitCode,true);
}
return0;//什么不做
}
也可以用线程派生类的方式。
C/C++code
.h文件
#defineWM_TESTWM_USER+1
classCTestThread:
publicCWinThread
{
DECLARE_DYNCREATE(CTestThread)
protected:
CTestThread();
virtual~CTestThread();
public:
virtualBOOLInitInstance();
virtualintExitInstance();
protected:
afx_msgvoidOnTest(WPARAMwParam,LPARAMlParam);
DECLARE_MESSAGE_MAP()
};
.Cpp文件
#include"stdafx.h"
#include"TestThread.h"
IMPLEMENT_DYNCREATE(CTestThread,CWinThread)
CTestThread:
:
CTestThread()
{
}
CTestThread:
:
~CTestThread()
{
}
BEGIN_MESSAGE_MAP(CTestThread,CWinThread)
ON_THREAD_MESSAGE(WM_TEST,OnTest)
END_MESSAGE_MAP()
BOOLCTestThread:
:
InitInstance()
{
returnTRUE;
}
intCTestThread:
:
ExitInstance()
{
returnCWinThread:
:
ExitInstance();
}
voidCTestThread:
:
OnTest(WPARAMwParam,LPARAMlParam)
{
AfxMessageBox("test");
}
调用的地方
CWinThread*m_pThrd;
//启动
m_pThrd=AfxBeginThread(RUNTIME_CLASS(CTestThread));
//需要执行线程中的操作时
m_pThrd->PostThreadMessage(WM_TEST,NULL,NULL);
//结束线程
HANDLEhp=m_pThrd->m_hThread;
if(hp)
{
if(WaitForSingleObject(hp,1)!
=WAIT_OBJECT_0)
{
TerminateThread(hp,0);
}
CloseHandle(hp);
}
这是框架,需要什么操作,自己定义、添加自己的线程消息就可以了。
MFC的控制中心――CWinThread:
:
Run()
(2013-02-2822:
32:
52)
转载▼
标签:
it
分类:
mfc
1.MFC的控制中心――CWinThread:
:
Run()
说CWinThread:
:
Run()是MFC的控制中心,一点也没有夸大。
在MFC中,所有来自于消息队列的消息的分派都是在CWinThread:
:
Run()函数中完成的,同 AfxWinMain()一样,这个函数也是对程序员是不可见的,其道理同AfxWinMain()的一样。
首先要提的一点是,对每 条从消息队列取出来的消息,MFC根据消息的类型,按照某个特定的模式进行分发处理,这个分发模式是MFC自己定义的。
固定的消息分发流程和在这个流程中 的可动态改变其行为的虚拟函数就构成了MFC的消息分发模式。
应用程序可以通过重载这些虚拟函数,来局部定制自己的的消息分发模式。
正是通过这些虚拟函数,MFC为应用程序提供了足够的灵活性。
下面讨论的所有代码都来自于MFC源代码中的../MFC/SRC/threadcore.cpp文件,它们都是CWinThread 的成员。
但是对话框程序没有对CWinThread:
:
Run()的调用。
新建一个SDI的项目,打断点,看看CWinThread:
:
Run()被调用时候的栈:
CWinThread:
:
Run()line468
CWinApp:
:
Run()line400
AfxWinMain(HINSTANCE__*0x00400000,HINSTANCE__*0x00000000,char*0x00151f2b,int1)line49+11bytes
WinMain(HINSTANCE__*0x00400000,HINSTANCE__*0x00000000,char*0x00151f2b,int1)line30
WinMainCRTStartup()line330+54bytes
KERNEL32!
7c816fd7()
很明显SDI和dialog在AfxWinMain函数中走的逻辑就已经不同了。
CWinThread:
:
Run()的结构
CWinThread:
:
Run()的代码如下:
//mainrunningroutineuntilthreadexits
intCWinThread:
:
Run()
{
ASSERT_VALID(this);
//fortrackingtheidletimestate
BOOLbIdle=TRUE;
LONGlIdleCount=0;
//acquireanddispatchmessagesuntilaWM_QUITmessageisreceived.
for(;;)
{
//phase1:
checktoseeifwecandoidlework
while(bIdle&&
!
:
:
PeekMessage(&m_msgCur,NULL,NULL,NULL,PM_NOREMOVE))
{
//callOnIdlewhileinbIdlestate
if(!
OnIdle(lIdleCount++))
bIdle=FALSE;//assume"noidle"state
}
//phase2:
pumpmessageswhileavailable
do
{
//pumpmessage,butquitonWM_QUIT
if(!
PumpMessage())
returnExitInstance();
//reset"noidle"stateafterpumping"normal"message
if(IsIdleMessage(&m_msgCur))
{
bIdle=TRUE;
lIdleCount=0;
}
}while(:
:
PeekMessage(&m_msgCur,NULL,NULL,NULL,PM_NOREMOVE));
}
ASSERT(FALSE); //notreachable
}
CWinThread:
:
Run()的处理过程如下:
先根据空闲标志以及消息队列是否为空这两个条件判断当前线程是否处于空闲状态(这个“空闲”的含义同操作系统的含义不同,是MFC自己所谓的“空闲”),如果是,就调用CWinThread:
:
OnIdle(),这也是我们比较熟悉的一个虚拟函数。
如果不是,从消息队列中取出消息,进行处理,直到消息队列为空。
在这里,我们发现,MFC不是调用GetMessage()从线程消息队列中取消息,而是调用PeekMessage()。
其原因在于,GetMessage()是一个具有同步行为的函数,如果消息队列中没有消息,GetMessage()会一直阻塞,使得线程处于睡眠状态,直到消息队列 中有一条或多条消息,操作系统才会唤醒该线程,GetMessage()才会返回,如果线程处于睡眠状态了,就不会使线程具有MFC所谓的“空闲”状态 了;而PeekMessage()则是一个具有异步行为的函数,如果消息队列中没有消息,它马上返回0,不会导致线程处于睡眠状态。
在上面的代码中,有两个函数值得探讨,一个是空闲处理函数OnIdle(),另外一个是消息分发处理函数PumpMessage()。
不要忽视 CWinThread的OnIdle()函数,它作了很多有意义的事情。
下面讨论PumpMessage(),OnIdle()将在后面的章节里讨论。
CWinThread:
:
Run()的核心――CWinThread:
:
PumpMessage()
标题强调了PumpMessage()的重要性,Run()是MFC的控制中心,而PumpMessage()又是Run()的核心,所以从MFC的真正控制中心是PumpMessage()。
PumpMessage()的代码极其简单:
BOOLCWinThread:
:
PumpMessage()
{
ASSERT_VALID(this);
if(!
:
:
GetMessage(&m_msgCur,NULL,NULL,NULL))
returnFALSE;
//processthismessage
if(m_msgCur.message!
=WM_KICKIDLE&&!
PreTranslateMessage(&m_msgCur))
{
:
:
TranslateMessage(&m_msgCur);
:
:
DispatchMessage(&m_msgCur);
}
returnTRUE;