摘要:本文主要以mfc线程为主题展开的概述,详细介绍了线程,线程与函数以及实例来说明,下面我们一起来看看原文。
线程简介
我们知道一般情况程序中的代码都是按顺序从头开始一行一行的执行以最后。中间不能出现同时执行的情况。比如一段代码调用两个函数
FunOne();
FunTwo();
只要当函数FunOne中的代码执行完才返回来执行FunTwo.假如逻辑上是有先后顺序那还真只能这样按顺序执行下来。不过有假如FunOne与FunTwo没有逻辑先后顺序,是相互独立的。比如两个函数分别处理两不同的文件one.text与two.txt.
这种情形就可以用到线程,弄两个线程去执行这两函数。这样两函数同时执行,提高了效率(如果单核的CPU可能没有真正的并行效果不明显,那多核CPU执行多线程那是能够真正达到并行执行,效果很明显的)。
实际上可以这样简单的理解线程,它是CPU的调度单位。而一个线程是对应一个函数。所以别把一个线程想得太复杂,就只是执行个函数而已。只不过执行的时候是并行执行罢了。如果只是简单的几个线程不涉及使用共同的资源,没其他啥关联。就完全跟简单的执行一个函数类似。只是如果多个线程间关系复杂就会涉及到啥同步问题,那样就有很多复杂的细节性问题。
线程间通信的方式
方式一:全局变量,各线程通过修改全局变量传递信息,通过循环检测查看信息。 方式二:消息传递,通过windows消息机制传递。
方式一问题主要有两个:第一是全局变量过多,不便于管理;第二个是循环检测过于缓慢,并且较不灵活,不能够迅速响应变化。
MFC中存在三种线程
A、 Ui线程:通过创建窗口得到,具备标准窗口的功能。
B、 工作者线程:通过CreateThread函数直接创建,不具备消息队列。
C、 带消息队列的工作者线程:通过继承CWinThread得到,具备消息队列。
A种和C种线程使用消息队列,对于使用者来说,这两种线程需要自己本身或其他线程向其发送消息,才进行相应工作,否则保持静默状态,该两种线程擅长实时处理外部信号。 B种线程不使用消息队列,可以用单个函数作为其线程的本体,适合处理步骤相对固定的算法。
线程与函数
线程函数必须是全局函数,或者是类的静态成员函数,因为非静态成员函数有this指针,而在进程中无法访问此指针。
但是静态成员函数只能访问静态成员,解决此问题途径:
1. 就是在调用静态成员函数时将this指针作为参数传入,通过该指针访问非静态成员。
2. 不将线程函数定义为类的静态成员函数,而是定义为类的友元函数,这样函数线程也可以有类成员函数相同的权限。
最简单示例
线程分工作线程与界面线程。这里就以工作线程为例
1.先来看个MFC中的创建线程的简单例子。
UINT ThreadFun(LPVOID pParam){ //线程要调用的函数
MessageBox(NULL,_T(“i am called by a thread.”), _T(“thread func”),MB_OK);
}
::AfxBeginThread(ThreadFun, NULL); //这就是创建一个线程并执行了,调用上面的函数弹出一个对话框。
2.示例分析
上面的线程是简单的不能再简单了吧。下面从两个来分析下。
a.首先是被调用的函数有啥讲究不? 当然有,被线程用到的函数格式必须是统一的,返回类型必须是UINT,函数只能有一个参数LPVOID.其中UINT就是个无符号的整形,LPVOID是void*,所以这个参数表示可以传任何类型的指针过来的。
b.函数AfxBeginThread的分析。
这个函数还有返回值CWinThread*的,如果你只是简单的创建一个线程并执行,就不用管了。但如果想要对创建的线程做其他操作就必须这样写。
CWinThread* pThread = ::AfxBeginThread(ThreadFun, NULL); //接下来做啥就直接调用pThead就行。
另外函数AfxBeginThread的参数有很多个,但很多都有默认值。下面是完整的参数
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc, //一个函数指针
LPVOID pParam, //void*类型的指针,可以传任何种类指针过来。
int nPriority = THREAD_PRIORITY_NORMAL, //线程优先级
UNT nStackSize = 0, //分配堆栈大小
DWORD dwCreateFlags = 0, //表示线程创建后是立即执行还是等会执行
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL //线程安全属性指针
);//用于创建工作者线程
上面的参数我们用的最多的是3个,其他一盘都默认值。
AFX_THREADPROC pfnThreadProc //函数指针肯定是必须要指定的,不然线程执行哪个函数去啊
LPVOID pParam //这是传给上面指定函数的参数。如果被调用的函数需要啥参数就只能在这里指定了。
DWORD dwCreateFlags //默认值为0表示创建线程后立即执行。如果是CREATE_SUSPEND则表示创建好后先挂起。必须通过ResumeThread来执行。
评论
查看更多