MFC多线程的创建

利用MFC可以创建两种线程,分别称之为工作线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。

工作线程的创建

创建工作线程分为三步:(1)线程函数的声明(2)线程函数的实现(3)创建(启动)线程
(1)线程函数的声明:
线程函数的声明必须在类外声明,格式如下:
UINT ThreadFunc(LPVOID lpParam);返回类型及LPVOID不能改变。
(2)线程函数的定义:

UINT  ThreadFunc(LPVOID  lParam)  
{  
	while(true){
		AfxMesageBox("子线程");
		Sleep(1000);
	}
}  

(3)线程函数的创建(启动)

创建线程有两种方式:
1)一般直接用AfxBeginThread(ThreadProc,this);

void CITTDlg::OnKMeansSegment()             //按钮点击执行  
{  

		AfxBeginThread(ThreadFunc, (LPVOID)this);//启动新的线程  

} 

2)首先创建CWinThread类的一个对象,然后调用该对象的成员函数CreateThread()来启动该线程。

用户界面线程

由于用户界面线程含有自己的消息循环,可以处理Windows消息,并可创建和管理诸如窗口和控件等用户界面元素。因此,这种线程较工作线程更为复杂。

创建用户界面线程的起点是从MFC的CWinThread类派生一个定制的线程类,而不是调用AfxBeginThead()函数。定制的线程类必须重载InitInstance()函数,该函数用来执行初始化任务,在创建线程时系统将调用InitInstance()函数。最好还要重载ExitInstane()函数,该函数是InitInstance()函数的对应,MFC在删除线程对象之前会调用ExitInstane()函数,以便线程能够在结束后清除自身。

用户界面线程的创建有两种方法,方法一是首先从CWinThread类派生一个类(必须要用宏DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE对该类进行声明和实现),然后调用AfxBeginThead()创建CWinThread派生类的对象进行初始化,启动线程运行。方法二是先通过构造函数创建类CWinThread的一个对象,然后由程序员调用函数::CreateThread来启动线程。通常CWinThread类的对象在该线程的生存期结束时将自动终止,如果程序员希望自己来控制,则需要将m_bAutoDelete设为FALSE。这样在线程终止之后,CWinThread类对象仍然存在,此时需要手动删除CWinThread对象。

用户界面线程的实现:

1.先建一个mfc界面(类为:testThread),在界面放置一按钮。
2.右键属性,添加类,选择MFC类,点击添加,选择基类为CWinThread,填写类名,如:CUIThread,自动生成UIThread.h和UIThread.cpp
3.给工程添加新界面IDD_UITHREADDLG,标题为“线程对话框”。 对界面改为IDD_UITHREADDLG,双击该界面创建一个基于CDialog的类CUIThreadDlg,包含CUIThreadDlg.h和CUIThreadDlg.cpp
4.在IDD_UITHREADDLG界面放置一按钮,双击进入函数,

void CUIThreadDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	AfxMessageBox("You Clicked The Left Button!");
	CDialog::OnLButtonDown(nFlags, point);
}

5.在UIThread.h中添加

#include "UIThreadDlg.h"

并在CUIThread类中添加protected变量

	CUIThreadDlg m_dlg;

6.分别重载InitInstance()函数和ExitInstance()函数:

BOOL CUIThread::InitInstance()
{
	m_dlg.Create(IDD_UITHREADDLG);
	m_dlg.ShowWindow(SW_SHOW);
	m_pMainWnd=&m_dlg;
	return TRUE;
}

int CUIThread::ExitInstance()
{
	m_dlg.DestroyWindow();
	return CWinThread::ExitInstance();
}

7.在主界面双击“用户界面线程”按钮按钮,进入函数添加消息响应函数:

在CtestThreadDlg.cpp的开头添加:#include “UIThread.h”

void CtestThreadDlg::OnUiThread()
{
	CWinThread *pThread=AfxBeginThread(RUNTIME_CLASS(CUIThread));
}

每单击一次主界面的“用户界面线程”按钮,都会弹出一个线程对话框,在任何一个线程对话框内按下鼠标左键,都会弹出一个消息框。




如果不想弹出界面,则在线程函数中实现想实现的线程功能。
1.先建一个mfc界面(类为:testThread),在界面放置一按钮。
2.右键属性,添加类,选择MFC类,点击添加,选择基类为CWinThread,填写类名,如:CUIThread,自动生成UIThread.h和UIThread.cpp

3.在UIThread.h的类内声明一个线程函数,函数名自定,我的类中的线程函数叫StartThread

UIThread.h:

#ifndef T_THREAD_H
#define T_THREAD_H 
#pragma once
#define WM_TEST  WM_USER + 105 //定义线程函数入口地址
class CUIThread: public CWinThread
{
	    DECLARE_DYNCREATE(MyThread)
		public:
   		MyThread();
		virtual BOOL InitInstance();
		virtual int ExitInstance();
		void StartThread(WPARAM wParam, LPARAM lParam);//线程函数
		DECLARE_MESSAGE_MAP();
};
#endif

4.UIThread.cpp:实现线程函数StartThread

首先先重写

BOOL InitInstance(); 

int ExitInstance();

两个函数的定义后,在定义线程函数时加上下面的语句

BEGIN_MESSAGE_MAP(MyThread, CWinThread)
	ON_THREAD_MESSAGE(WM_TEST, StartThread)
END_MESSAGE_MAP()

这三条代码的作用是将线程消息传递路由定义好,接受到WM_TEST信号,则跳转到函数StartThread,执行该函数。

void CUIThread::StartThread(WPARAM wParam, LPARAM lParam)
{
	while (true)
	{
    		AfxMessageBox("子线程");
    		Sleep(1000);
	}

}

然后在主线程的按键消息函数中开启线程,开启线程的方式是先声明定义一个线程类指针

MyThread* p_MyThread;

再用AfxBeginThread获得线程指针

void CtestThreadDlg::OnBnClickedOk()
{
	// TODO:  在此添加控件通知处理程序代码

	p_MyThread= (MyThread*)AfxBeginThread(RUNTIME_CLASS(CUIThread), );
	p_MyThread->ResumeThread();//启动线程
	p_MyThread->PostThreadMessage(WM_TEST, 15, NULL);//发送WM_TEST消息

}

5.子线程也可以向主线程发送消息:
在子线程的UIThread.h中添加

#define WM_MESSAGEWM_USER+200//向主线程发送消息,用于返回相关信息

在UIThread.cpp中发送该消息

void CUIThread::StartThread(WPARAM wParam, LPARAM lParam)
{
	   wParam++;
		if(wParam<20)
		{
			AfxMessageBox("OK");
			Sleep(1000);
		}
		else{
			AfxMessageBox("NO");
			::SendMessage(AfxGetMainWnd()->m_hWnd,,WM_MESSAGE,0,0);//向主线程发送消息
		}
}

6.主线程接受消息,并执行相关函数。
在MFC类向导中为CtestThreadDlg类添加消息,点击添加自定义消息,添加UIThread.h发送的消息名字WM_MESSAGE,点击确定,自动生成消息响应函数。

afx_msg	LRESULT CtestThreadDlg::OnMessage(WPARAM wParam,LPARAM lParam)
{
		AfxMessageBox("主函数接收到子线程发送的消息");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值