您的位置:首页 > 其它

MFC中工作线程的创建

2012-09-23 17:09 253 查看
最近做的东西涉及到多线程编程方法,所以找了点资料

本文主要描述基于MFC的多线程技术中的工作者线程,包括线程的建立、传递参数、互斥对象保护以及线程的销毁。还将探讨线程函数作为类的成员函数的情况。

  首先需要说明的是工作者线程和界面线程的区别,界面线程(UI线程)指的是包含有消息队列的线程,可以使用消息机制相互通信;工作者线程则没有消息队列,能够发送消息,但是不能够处理Windows消息。

  MFC中的建立一个线程的通常使用AfxBeginThread,参考MSDN 使用 C++ 和 MFC 进行多线程编程 ,此函数有两个版本,创建UI线程需要先从CWinThread类派生类,并作为第一个参数传递给AfxBeginThread;创建工作者线程只需要定义线程处理函数并将函数地址作为AfxBeginThread的第一个参数即可。

  工作者线程只允许线程创建时传入一个LPVOID型的指针,需要传入大量参数时可以定义一个结构体,把结构体指针作为参数传入线程函数,线程内部通过强制类型转换得到结构体指针。

  线程的入口函数一定是全局函数或者是静态函数。线程函数作为类的成员函数时,必须声明为静态函数,因为类成员函数在编译时会添加this指针,静态方法属于类本身而不属于某个对象,不分配this指针,可以保证正确传入的LPVOID指针。另外,类的静态方法只能访问类的静态成员变量,在类的方法中创建线程时一般考虑传入this指针,方便其访问类中的成员变量。此时类的对象存在,线程可以通过对象的指针访问类的成员变量以及成员函数。

  注:若在类中声明静态变量,需要在实现文件中初始化,否则链接会出现“无法解析的外部符号”。原因是类中的静态变量只是声明。静态变量属于类本身,不属于任何一个对象,不能在对象构造函数中初始化,一般是在main函数前面采用:

<数据类型> <类名> :: <静态数据成员名> = <值>

的格式初始化,引用类的静态成员变量是时须按照:

<类名> :: <静态成员名>

的格式进行引用。

  何时需要使用线程同步以及采用什么样的线程同步请参照MSDN 多线程处理:何时使用同步类 多线程处理:如何使用同步类 这里主要讨论CSingleLock的使用,首先需要一个CCriticalSection对象,一般是某个类的静态成员,在类的成员函数里,可以使用CCriticalSection对象的地址创建一个CSingleLock对象(局部变量),CSingleLock对象析构时会自动对资源进行解锁,因此即使函数异常退出,资源依然可以正常释放。当然如果函数只需要Lock一次资源,则使用CSingleLock可以不UnLock,析构函数会自动UnLock。

  工作者线程的正常退出为其控制函数的正常返回或者从要终止的线程内调用 AfxEndThread。推荐在线程中判断返回标志,需要时返回。如果需要在外部监视工作者线程的状态,请调用 GetExitCodeThread 函数,有两种方法:

  1. 将 m_bAutoDelete 数据成员设置为 FALSE。这使 CWinThread 对象在线程终止后仍可以继续存在。然后可以在线程终止后,访问 m_hThread 数据成员。但是,如果使用此方法,就得销毁 CWinThread 对象(调用CWinThread 的Delete方法),因为框架不会自动删除该对象。这是首选方法。

  2. 单独存储线程的句柄。创建线程后,(使用 ::DuplicateHandle)将其 m_hThread 数据成员复制到其他变量,并通过该变量访问该成员。这样,终止后即会自动删除对象,并且仍然可以找到线程终止的原因。请注意:在可以复制句柄之前,线程不终止。执行此操作的最安全的方式是将 CREATE_SUSPENDED
传递到 AfxBeginThread,存储句柄,然后通过调用 ResumeThread 继续执行线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: