MFC 多线程编程注意事项(1)发表日期:2010-12-17 1,表现——错误示例 关于启动线程时传输窗口对象(指针?句柄?)的问题: 在选择菜单中的开始线程后: void cmainframe::onmenu_start() { ... afxbeginthread(mythread, this); ... } 线程函数如下: uint mythread(lpvoid pparam) { cmainframe* pmainfrm = (cmainframe *)pparam; ... } 问题一: 这样的代码是不是有问题? (文档中说线程间不能直接传输mfc 对象的指针,应该通过传输句柄实现) 问题二: 这样使用开始好像没有问题,直接通过pmainfrm 访问窗口中的view 都正常。 但发现访问状态条时: pmainfrm->m_wndstatusbar.setpanetext(2, "test); 出现debug assertion failed!(在窗口线程中没有问题) 位置是wincore.cpp 中的 assert((p = pmap->lookuppermanent(m_hwnd)) != null || (p = pmap->lookuptemporary(m_hwnd)) != null); 为什么访问view 能正常,但访问状态条时不可以呢? 问题三: 如果通过传输句柄实现,怎样做呢? 我用下面的代码执行时有问题: void cmainframe::onmenu_start() { ... hwnd hwnd = getsafehwnd(); afxbeginthread(mythread, hwnd); ... } uint mythread(lpvoid pparam) { cmainframe* pmainfrm = (cmainframe *)(cwnd::fromhandle((hwnd)pparam)); ... } 执行时通过线程中得到pmainfrm,访问其成员时不正常。 网友:hewwatt 大致原因解释如下: 1. mfc 的大多数类不是线程安全的,cwnd 及其消息路由是其中之最 2. mfc 界面类的大多数方法,最后都是通过sendmessage 实现的,而消息处理的过程中会引发其他消息的发送及处理。如果消息处理函数本身不是线程安全的,你从工作线程中调用这些方法迟早会同你界面线程的用户消息响应发生冲突 3. cxxxx::fromhandle 会根据调用者所在线程查表,如果查不到用户创建的cxxxx 对应对象,它会创建一个临时对象出来。由于你在工作线程中调用该方法,当然不可能查到界面主线程中你所建立起来的那个对象了。这时mfc 会你创建一个临时对象并返回给你,你根本不可能期望它的成员变量会是有意义的。 所以要用也只能用cwnd::fromhandle,因为它只包含一个m_hwnd 成员。 不过,要记住跨线程直接或间接地调用::sendmessage,通常都是行为不可预测的。 2. 原因分析 MFC 界面包装类(多线程时成员函数调用的断言失败) 日期:2006...