以下是 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();//运行