1、进程和线程的基本概念:
在计算机系统中,一个正在运行的应用程序就叫做一个进程,一个进程可以有多个线程,进程的任务是有这个进程的所有线程共同配合来完成的。一个进程至少有一个线程,叫做主线程。
2、工作线程的创建:
如何创建一个工作线程是一个比较容易的,只要清楚开启线程函数的原型就很简单了。开启线程的函数是 AfxBeginThread,它主要有两种类型,分别是:
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int 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 );
第一个函数可以从参数中看到,只有前两个参数需要传递参数,第一个参数是pfnThreadProc用来指明被作为线程的函数的地址;而第二个参数是需要传递给线程函数的一个32为的参数指针,通过该指针可以向线程传递任何需要的参数。
第二个函数可以从参数中看到,只有前面一个参数需要传递,第一个参数是一个类类型的指针pThreadClass,通过 RUNTIME_CLASS 来为线程获取一个类类型的对象。
了解了开启线程函数的格式之后,就是创建工作线程了:通过一个例子来说明如何创建一个工作线程:
例子:编写一个应用程序,当在程序窗口按下鼠标左键的时候,就启动一个线程,该线程在屏幕上显示一个信息框。
实现:(1)用MFC创建一个单文档应用程序
(2)在试图类实现文件(.cpp文件)中编写一个准备作为线程的函数
//线程函数的实现部分
UINT MessageThread(LPVOID pParam)
{
char* pMessage=(char*)pParam;
CWnd* pMainWnd=AfxGetMainWnd();
::MessageBox(
pMainWnd->m_hWnd,//窗口句柄
pMessage,//窗口内显示的内容
"Thread Message",//窗口的标题
MB_OK);
return 0;
}
(3)在视图类的鼠标左键消息响应函数中创建和开启线程。
void CThreadView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//创建开启线程
AfxBeginThread(
MessageThread,//指定线程函数
"Greetings from your thread!"//传递到线程函数中的线程参数pParam
);
CView::OnLButtonDown(nFlags, point);
}
3、用户界面线程的创建
用户界面线程跟工作线程的区别是用户界面线程需要创建线程的窗口工作界面。于是就应用到创建开始线程的第二个函数模型:
CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
用户界面线程必须包含有消息循环,一边可以处理用户消息。应该还记得,MFC把程序处理消息的窗口函数封装到CCmdTarget类中,而在这个CCmdTarget类的基础上,又封装了创建线程的一些操作,从而派生出CWinThread类。因此,为了创建可以响应消息的用户界面线程,在程序设计时,必须要以MFC的CWinThread类为基类派生一个线程类,而且在一般的时候需要重写类的InitInstance()和ExitInstance()函数,在InitInstance()中标写线程的初始化代码(主要是创建窗口),而在ExitInstance()函数中编写撤销线程对象的代码。
详细了解通过一个例子来说明:编写一个应用程序,当用户在程序的主窗口按下鼠标左键时,会启动一个用户界面线程,当用户在线程窗口按下时表左键时,会弹出一个对话框的提示信息。
实现:(1)用MFC创建一个单文档的应用程序
(2)使用类向导以CWinThread类为基类派生CMyThread类//这个是用来传递到创建开启线程的函数中的参数,同时以CFrameWnd类为基类派生CMyWnd类。//这是为了创建线程窗口做准备,即创建自己的线程窗口。
(3)在应用程序视图类的实现文件中包含头文件
#include“MyThread.h”//这是通过基类派生出来的线程类的头文件
(4)在CMyThread类实现文件中包含头文件
#include“MyWnd.h”//这是在线程类当中添加创建的窗口类的头文件,以便在线程类当中初始化窗口
(5)在CMyThread::InitInstance()中创建线程中的窗体
//利用线程类来实现用户界面多线程,主要是在产生线程类的同时要创建出相应的用户界面
BOOL CMyThread::InitInstance()
{
//这部分主要是在线程类当中添加相应的功能,在这里是初始化一个用户界面
// TODO: perform and per-thread initialization here
//创建窗口的程序
CMyWnd* pFrameWnd=new CMyWnd();//利用窗口类定义一个窗口指针
pFrameWnd->Create(NULL,"Thread Window");//创建窗口
pFrameWnd->ShowWindow(SW_SHOW);//显示窗口
pFrameWnd->UpdateWindow();//更新窗口
return TRUE;
}
(6)在CMyWnd类中声明鼠标消息响应函数,并加以实现,这就是在创建的线程窗口当中添加相应的消息响应函数的过程。
void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
char * pMessage="This is a window thread";
CWnd* pMainWnd=AfxGetMainWnd();//获得主窗口的指针
::MessageBox(NULL,//指定窗口的参数、
pMessage,//对话框显示的内容
"Thread Message",//对话框的标题
MB_OK
);
CFrameWnd::OnLButtonDown(nFlags, point);
}
(7)在应用程序的视图类当中添加鼠标消息响应函数,这个是为了创建和开启用户界面线程。
//启动线程类
void CThreadClassView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//创建线程
//RUNTIME_CLASS运行时获得相应的线程类
AfxBeginThread(RUNTIME_CLASS(CMyThread));//CMyThread是创建的线程类
CView::OnLButtonDown(nFlags, point);
}