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