MFC子线程消息循环的实现

MFC子线程消息循环的实现

2023年6月22日发(作者:)

MFC⼦线程消息循环的实现 这段时间要做⼀个⼯具要从服务器取⼀些数据,做⼀些处理后保存. 由于数据量⼤和服务器响应的问题, 所以准备⽤多线程的⽅式从服务器取数据. 程序逻辑很简单, 所以就⽤着复杂的同步机制了, 就每⼦线程向主线程发送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() // 申明消息映射表, 这个也很重要, 因为你要处理消息嘛};

// #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; (_T("Lparam is %d, wparam is %d"), lparam, wparam); AfxMessageBox(strMsg); return 0;}BOOL CMyWorkThread::InitInstance(){ return TRUE; // 这个很重要哦, 返回false的话, 这个线程是不会有消息循环的}写完这段代码习惯性的先编译⼀下, 结果是编译报错了: error C2440: “static_cast”: ⽆法从“LRESULT (__thiscallCMyWorkThread::* )(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); 想结束线程的时候程序出异常了. ⽽且这个异常是在是报出来的, 这是VC的库⽂件啊. 后我把InitInstance这函数下⾯这样BOOL CMyWorkThread::InitInstance(){ m_pMainWnd = NULL; m_pActiveWnd = NULL; m_bAutoDelete = FALSE; return TRUE;}程序就可以正常⼯作, ⾄于这是为什么? 我也还没搞明⽩, 还得继续探索. 不过种情况下我们得⾃⼰去负责删除这个线程对象了.

发布者:admin,转转请注明出处:http://www.yc00.com/web/1687422660a8913.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信