MFC用户界面多线程实例2

         以下是 MFC 用户界面线程相关知识                    

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

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

用户界面线程的创建有两种方法:
方法一:首先从 CWinThread 类派生一个类(必须要用宏 DECLARE_DYNCREATE 
和 IMPLEMENT_DYNCREATE  对该类进行声明和实现),然后调用 AfxBeginThread() 创建 CWinThread 派生类的对象进行初始化,启动线程运行。

方法二:先通过构造函数创建派生类 CWinThread 的一个对象,然后由程序员调用函数 ::CreateThread 来启动线程。通常CWinThread 派生类的对象在该线程的生存周期结束时将自动终止,如果程序员希望自己来控制,则需要将 m_bAutoDelete 设置为FALSE。这样在线程终止之后, CWinThread 派生类对象仍然存在,此时需要手动删除CWinThread 对象。

             MFC 消息处理相关知识                               
函数原型:LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);   
函数原型:BOOL    PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
区别:
PostMessage 将一个消息放入(寄送)到与指定窗口创建的线程相联系的消息队列里,完成则立即返回(不等待线程处理消息就返
回)。消息队列里的消息通过调用 GetMessage 和 PeekMessage 取得。

SendMessage 将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序, 直到窗口程序处理完消息再返回。

       消息映射: ON_MESSAGE 和 ON_THREAD_MESSAGE
       用户自定义消息通常定义在 WM_USER (0x0400)至 0x7FFF 范围内,用户定义的任何消息都不是正规的windows 窗口消息WM_MESSAGE 。用户自定义消息必须明确地在程序中用ON_MESSAGE 宏来声明,从而绑定一个消息响应函数。

ON_MESSAGE : 绑定一个自定义的消息和该消息的响应函数。
ON_THREAD_MESSAGE : 当使用 CWinThread 类的时候,必须用 ON_THREAD_MESSAGE 来代替 ON_MESSAGE。 
特别注意:使用用户界面线程时,推送消息用 CWinThread 的成员函数 PostThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam);  

 m_childThread->PostThreadMessage(xxx,xxx,xxx); 其推送的消息只对本身类 对象实例。其他对象实例无法接收该消息。简单的说就是每个对象实例拥有内部消息栈,不共享。所以采用消息机制做多线程是不适合动态创建若干线程,且每个线程正常工作。

 退出线程发送 WM_QUIT 消息。

MFC用户界面线程实例:

一、采用消息循环的用户界面线程实例

头文件:

/*
* Copyright (c) 2014-2020, MFC多线程学习
* All rights reserved.
*
* 文件名称:FireUIThreadMsg.h
* 文件标识:
* 摘    要:MFC用户界面线程,采用MFC消息机制
* 
* 当前版本:1.0
* 作    者:XXX
* 完成日期:2014-06-16
*
* 取代版本:无
* 原 作 者:
* 完成日期:
*/

#pragma once

#define WM_MSG_FIREUIMSG  (WM_USER+11) //自定义用户消息

// CFireUIThreadMsg

class CFireUIThreadMsg : public CWinThread
{
	DECLARE_DYNCREATE(CFireUIThreadMsg)

public:
	CFireUIThreadMsg();           // 动态创建所使用的受保护的构造函数
	virtual ~CFireUIThreadMsg();

public:
	virtual BOOL InitInstance();
	virtual int ExitInstance();

public:                        //用户添加函数
	afx_msg void FireUIWork(WPARAM wParam, LPARAM lParam); //消息处理函数
    
	CBrush m_Brush;
	CPoint m_Point;
	int    m_num;

	CFireUIThreadMsg(int num);

	void KillThread();

protected:
	DECLARE_MESSAGE_MAP()
};


源文件:

// FireUIThreadMsg.cpp : 实现文件
//

#include "stdafx.h"
#include "Firework.h"
#include "FireUIThreadMsg.h"


// CFireUIThreadMsg

IMPLEMENT_DYNCREATE(CFireUIThreadMsg, CWinThread)

CFireUIThreadMsg::CFireUIThreadMsg()
{
	m_bAutoDelete = FALSE;
}

CFireUIThreadMsg::~CFireUIThreadMsg()
{
}

BOOL CFireUIThreadMsg::InitInstance()
{
	// TODO: 在此执行任意逐线程初始化
	return TRUE;
}

int CFireUIThreadMsg::ExitInstance()
{
	// TODO: 在此执行任意逐线程清理
	return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(CFireUIThreadMsg, CWinThread)
	ON_THREAD_MESSAGE(WM_MSG_FIREUIMSG, &CFireUIThreadMsg::FireUIWork) //消息映射宏
END_MESSAGE_MAP()


// CFireUIThreadMsg 消息处理程序
void CFireUIThreadMsg::FireUIWork(WPARAM wParam, LPARAM lParam)
{
	CString tem;
	tem.Format("%d", m_num);
	AfxMessageBox(tem);
}

CFireUIThreadMsg::CFireUIThreadMsg(int num)
{
	m_num = num;
}

void CFireUIThreadMsg::KillThread()
{
	PostThreadMessage(WM_QUIT, 0 , 0);
}


二、采用事件等待循环处理实例

头文件:

/*
* Copyright (c) 2014-2020, MFC多线程学习
* All rights reserved.
*
* 文件名称:FireUIThread.h
* 文件标识:
* 摘    要:MFC用户界面线程,采用循环机制。不使用MFC消息
*           适用于动态创建大量线程。
* 
* 当前版本:1.0
* 作    者:XXX
* 完成日期:2014-06-16
*
* 取代版本:无
* 原 作 者:
* 完成日期:
*/

#pragma once



// CFireUIThread

class CFireUIThread : public CWinThread
{
	DECLARE_DYNCREATE(CFireUIThread)

//protected:
public:
	CFireUIThread();           // 动态创建所使用的受保护的构造函数
	CFireUIThread(CDC *pDC, CRect rect);
	virtual ~CFireUIThread();

public:
	virtual BOOL InitInstance();
	virtual int  ExitInstance();
	virtual void Delete();
protected:
	DECLARE_MESSAGE_MAP()

public:
	void FireworkDisplay();

	void KillThread();
private:
	  
	HANDLE m_hEventKill;
	HANDLE m_hEventDead;
	
};

源文件:

// FireUIThread.cpp : 实现文件
//

#include "stdafx.h"
#include "Firework.h"
#include "FireUIThread.h"


// CFireUIThread

IMPLEMENT_DYNCREATE(CFireUIThread, CWinThread)

CFireUIThread::CFireUIThread()
{
	m_bAutoDelete = FALSE;

	m_hEventKill = CreateEvent(NULL, TRUE, FALSE, NULL);
	m_hEventDead = CreateEvent(NULL, TRUE, FALSE, NULL);
}

CFireUIThread::~CFireUIThread()
{
	CloseHandle(m_hEventKill);
	CloseHandle(m_hEventDead);
}

BOOL CFireUIThread::InitInstance()
{
	// TODO: 在此执行任意逐线程初始化
	while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT)
	{
		FireworkDisplay();
	}
	//return TRUE;
	// avoid entering standard message loop by returning FALSE
	return FALSE; //不进入消息循环。特别注意
}

int CFireUIThread::ExitInstance()
{
	// TODO: 在此执行任意逐线程清理
	return CWinThread::ExitInstance();
}

void CFireUIThread::Delete()
{
	CWinThread::Delete();

	SetEvent(m_hEventDead);
}


void CFireUIThread::KillThread()
{
	SetEvent(m_hEventKill);

	SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
	WaitForSingleObject(m_hEventDead, INFINITE);
	
	delete this;
}

BEGIN_MESSAGE_MAP(CFireUIThread, CWinThread)
END_MESSAGE_MAP()


// CFireUIThread 消息处理程序
void CFireUIThread::FireworkDisplay()
{
//线程处理函数
}


创建线程代码片:

	CWinThread* pThread = new CFireUIThreadMsg(nIDTimerEvent);
	pThread->CreateThread(CREATE_SUSPENDED);
	pThread->ResumeThread();//运行

记得结束线程,释放内存。



发布了34 篇原创文章 · 获赞 6 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章