③DWORD ResumeThread(HANDLE hThread);
该函数用于结束线程的挂起状态,执行线程。
④VOID ExitThread(DWORD dwExitCode);
该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。
⑤BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。使用TerminateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的.执行,但并不释放线程所占用的资源。因此,一般不建议使用该函数。
⑥BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam);
该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回。调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败。
2) MFC对多线程编程的支持
MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。
工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。但对于Win32的API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务。
在MFC中,一般用全局函数AfxBeginThread()来创建并初始化一个线程的运行,该函数有两种重载形式,分别用于创建工作者线程和用户界面线程。两种重载函数原型和参数分别说明如下:
①CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,LPVOID pParam,
nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize=0,
DWORD dwCreateFlags=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
②CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass,
int nPriority=THREAD_PRIORITY_NORMAL,UINT nStackSize=0,
DWORD dwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
一般情况下,调用AfxBeginThread()来一次性地创建并启动一个线程,但是也可以通过两步法来创建线程:首先创建CWinThread类的一个对象,然后调用该对象的成员函数CreateThread()来启动该线程。
③virtual BOOL CWinThread::InitInstance();
重载该函数以控制用户界面线程实例的初始化。初始化成功则返回非0值,否则返回0。用户界面线程经常重载该函数,工作者线程一般不使用InitInstance()。
④virtual int CWinThread::ExitInstance();
在线程终结前重载该函数进行一些必要的清理工作。该函数返回线程的退出码,0表示执行成功,非0值用来标识各种错误。同InitInstance()成员函数一样,该函数也只适用于用户界面线程。
3.2 VC++下多线程局域网聊天程序
聊天程序是现代生活中不可缺少的通信工具,为了在局域网中实现点对点的实时通信,在VC++的编程环境中,利用套接字库技术和多线程编程技术实现聊天程序。
1) 界面设计。界面设计如图1所示。
2) 函数
void CMyQQDlg:: SendMsg() //发送消息
void CMyQQDlg:: SendFile() //发送文件
void CMyQQDlg:: Caputer() //抓取屏幕
void CMyQQDlg::AddMsgList(CString IP,CString str) //添加信息于LISTBOX 控件中
CString CMyQQDlg::GetError(DWORD error) //返回错误信息
int CMyQQDlg::GetLocalHostName(CString &sHostName) //获得本地计算机名称
int CMyQQDlg::GetIpAddress(const CString &sHostName, CString &sIpAddress)//获得本地IP
int CMyQQDlg::GetNamebyAddress(const CString &IpAddress,CString &sYouName)//获得对方计算机名称
3) 线程启动
pThreadLisen=::AfxBeginThread(_ListenTcpThread,this); //开始TCP线程
pThreadLisen=::AfxBeginThread(_UDPThread,this); //开始UDP线程
4) 服务器线程
UINT _ListenTcpThread(LPVOID lparam) //TCP监听线程
UINT _UDPThread(LPVOID lparam) //UDP接受信息线程开始
5) 客户端线程
UINT _SendFileThread(LPVOID lparam) //发送文件线程