MFC 子线程消息循环的实现
来源:互联网 发布:华为网络通信设备介绍 编辑:程序博客网 时间:2024/05/20 08:25
这段时间要做一个工具要从服务器取一些数据,做一些处理后保存. 由于数据量大和服务器响应的问题, 所以准备用多线程的方式从服务器取数据. 程序逻辑很简单, 所以就用着复杂的同步机制了, 就每子线程向主线程发送windows消息报告一下状态就可以了. 主线程是个对话框程序. 本来一切都挺简单的, 可前两天领导跟我说:"我们准备尝试一下测驱动开发, 就从你这个小工具开始吧." 当时我说好, 可是后来想想一个对话框怎么用cpp unit去测呢. 所有子线程的消息都发到主线程去了, cpp unit又怎么测这个呢.
后来我想了想, 有没有什么东西能代替界面接收这些消息呢? 我也有段时间没做过界面相关的工作了, 还记得<<深入浅出MFC>>提到过每个继承自CCmdTarget的类都有消息处理的能力, 而CWinThread正是它的子类, 我是不是可以另外建一个UI线程(但不显示任何窗口)来代替主线程接收这些消息呢? 于是我做准备试一下. 书上说的建一UI线程很简单, 可我实际操作的时候还是遇到了一些问题. 下面是我的实验过程,是在VC2010下做的, 希望能对遇到同样问题的朋友有点帮助.
1. 从CWinThread继承一个自己的线程类
//MyWorkThread.h
#define WM_MYMESSAGE (WM_USER + 1) // 自定义消息, 就是我要发送的消息class CMyWorkThread : public CWinThread{ DECLARE_DYNCREATE(CMyWorkThread)public: afx_msg LRESULT OnThreadMessage( LPARAM lparam ,WPARAM wparam); // 自定消息的处理函数 BOOL InitInstance(); // 重写这个函数, 很重要哦 DECLARE_MESSAGE_MAP() // 申明消息映射表, 这个也很重要, 因为你要处理消息嘛};
// MyWorkThread.cpp
#include "stdafx.h"#include "MyWorkThread.h"
IMPLEMENT_DYNCREATE(CMyWorkThread, CWinThread)
BEGIN_MESSAGE_MAP(CMyWorkThread, CWinThread) ON_THREAD_MESSAGE(WM_MYMESSAGE, OnThreadMessage) // 这里用的不是ON_MESSAGE, 而是ON_THREAD_MESSAGEEND_MESSAGE_MAP()
LRESULT CMyWorkThread::OnThreadMessage(LPARAM lparam, WPARAM wparam){
// 这个消息响应函数没干什么实事, 就是显示一下收到了什么参数 CString strMsg; strMsg.Format(_T("Lparam is %d, wparam is %d"), lparam, wparam); AfxMessageBox(strMsg);
return 0;}
BOOL CMyWorkThread::InitInstance(){ return TRUE; // 这个很重要哦, 返回false的话, 这个线程是不会有消息循环的}
写完这段代码习惯性的先编译一下, 结果是编译报错了: error C2440: “static_cast”: 无法从“LRESULT (__thiscall CMyWorkThread::* )(LPARAM,WPARAM)”转换为“void (__thiscall CWinThread::* )(WPARAM,LPARAM)” 在匹配目标类型的范围内没有具有该名称的函数
原来OnThreadMessage(LPARAM lparam ,WPARAM wparam)参数写反了, 真是眼睛瞎啊, 应该是WPARAM在前, LPARAM在后啊.于是我把这个函数改成
afx_msg LRESULT OnThreadMessage( WPARAM Wparam ,LPARAM lparam);
再编译, 还是报错了, error C2440: “static_cast”: 无法从“LRESULT (__thiscall CMyWorkThread::* )(WPARAM,LPARAM)”转换为“void (__thiscall CWinThread::* )(WPARAM,LPARAM)”
唉, 我咋就这样不顺利呢, 咋还报这个错, 正常的ON_MESSAGE消息处理函数不都是这样写的吗. 我开始怀疑是不是基类的函数指针不能接受的子类的函数? 于是我回过头去看MFC自己生成的对话框的添加消息映射代码:
ON_BN_CLICKED(IDC_BTN_SEND_MSG, &CScanDirDlg::OnBnClickedBtnSendMsg)
没错啊, 它也是用子类自己的函数做处理函数的啊, 难道非得要用&CScanDirDlg::OnBnClickedBtnSendMsg这样的形式? 于是呼我又把添加消息映射的代码改成
ON_THREAD_MESSAGE(WM_MYMESSAGE, &CMyWorkThread::OnThreadMessage) 再重新编译. 天哪, 还是报同样的错误. 这个问题纠结我了一个晚上啊, 我去百度, google都没有找到上体什么原因. 我好歹也写了几年程序了, 就不信还解决不了这个问题 !! 于是今天继续奋斗, 朋友们可别笑我啊, 写几年程序的人连这样的错误都没发现? 我想很多朋友都跟我有过类似的经历吧. 今天我又看了一眼那个错误信息, 突然之间眼前一亮, 妈的, 原来是返回值类型不匹配啊. 惭愧啊, 看出了这个错误我差点没晕过去, 真是哭笑不得啊.
2 纠正了前面那错误后编译终于通过了. 接下来该创建线程并测一下能不能正常工作了, 于是我在对话框的OnOK函数里写下了下面这段代码:
m_pWorkThread = AfxBeginThread(RUNTIME_CLASS(CMyWorkThread)); // CWinThread* m_pWorkThread是对话框的一个成员
// 这个线程只用来接收消息, 不需要线程函数
又在另一个按钮响应函数写了下面这段代码:
m_pWorkThread->PostThreadMessage(WM_QUIT, 0, 0); // 不是PostMessage() 哦
期待的对话框出现了. 可是新的问题又产生了, 那就是当我调用
m_pWorkThread->PostThreadMessage(WM_QUIT, 0, 0); 想结束线程的时候程序出异常了. 而且这个异常是在threadcore.cpp是报出来的, 这是VC的库文件啊. 后我把InitInstance这函数下面这样
BOOL CMyWorkThread::InitInstance(){ m_pMainWnd = NULL; m_pActiveWnd = NULL;
m_bAutoDelete = FALSE; return TRUE;}
程序就可以正常工作, 至于这是为什么? 我也还没搞明白, 还得继续探索. 不过种情况下我们得自己去负责删除这个线程对象了.
- MFC 子线程消息循环的实现
- MFC的消息循环
- MFC 定时触发器实现循环给指定线程进行发送消息
- 子线程中定义消息,进行消息循环
- 独立线程实现消息循环的Delphi定时器类
- Activity、Service、子线程之间的消息传递轻松实现
- MFC的消息循环&MFC的消息路由
- 091021(星期三)MFC线程消息循环4,Using Messages and Message Queues的msdn描述
- 记一次进程线程dll和MFC消息循环的系列问题
- 在delphi线程中实现消息循环
- 在delphi线程中实现消息循环
- MFC 实现两个子线程交叉运行
- 主线程和子线程中的消息循环
- 线程消息循环与通常消息循环的一点区别
- MFC模态对话框的消息循环
- MFC主线程安全关闭子线程的方法:使用PostThreadMessage在Win32线程间传递消息
- MFC中的消息循环
- MFC消息循环
- Option Menu && Context Menu的使用
- 一个被网易抛弃的孤儿~~~~~~~
- lua脚本语言
- 35岁前程序员要规划好的四件事,健康居首位
- 用DirectShow实现QQ的音视频聊天功能
- MFC 子线程消息循环的实现
- gcc 笔记 C Dialect Options
- 基于DirectShow的MPEG-4视频传输系统的研究与实现
- HULU2012校招笔试体会
- hdu 1200 To and Fro
- 隐私保护利器-----开辟密盘
- Ubuntu 9.10 构建Linux内核树
- C语言中不同数据类型间混合运算的转换规则
- hdu 1715 大菲波数(Easy)