MFC是在类层次上的线程安全而不是在对象层次上的线程安全.
如果把一个CWnd *P传递到另外一个线程,在这个线程中CWnd的有些成员
函数将不能使用,因为在MFC内部维护一个HWND和MFC对象间的映射,但这个映射
不能跨线程,所以在一个线程中把一个CWnd *P传递到另外一个线程,另外一个
线程只有CWnd *而没有相应的HWND的这个映射,所以出现ASSERT错误.
解决方案:
1、你可以向主线程发送自定义消息,然后在这个自定义消息中调用UpdateData,就可以解决问题。
或者使用其他方法来手动的修改数据,比如调用SetWindowText来改变窗口标题而不是用一个string然后Update等等,具体实现很灵活。
推荐使用前一种方法。
2、传递一个m_hWnd,然后在另外一个线程中调用CWnd::FromHandle(m_hWnd);
可行的是使用第一种方案,其中两种方式都可以实现。第二种方案没验证过。
另外的解释:
当创建窗口的线程和UpdateData调用所在的线程不是同一线程的时候MFC就会出错。因为MFC把部分信息储存在线程的TLS中,这些信息对于MFC的执行非常重要,因此MFC会在很多代码里面检查线程状态是否正确。所以这里不能用UpdateData。你可以向主线程发送自定义消息,然后在这个自定义消息中调用UpdateData,就可以解决问题。或者使用其他方法来手动的修改数据,比如调用SetWindowText来改变窗口标题而不是用一个string然后Update等等,具体实现很灵活。推荐使用前一种方法。
还是不行~
UINT ThreadProc(LPVOID lParam);
class CMyDialog :public CDialog
{
.....
UINT returnThread(LPVOID lParam);
void callThread() { AfxBeginThread(ThreadProc,this-> m_hWnd) };
.....
}
UINT CMyDialog::returnThread(LPVOID lParam)
{
.......
CMyDialog dlg;
dlg.Attach((HWND)lParam);
dlg.UpdateData(FALSE); //改后在RELEASE版本模式下都有问题了!zh :(
.......
}
UINT ThreadProc(LPVOID lParam)
{
CMyDialog mydlg;
mydlg.FromHandle((HWND)lParam);
return mydlg.returnThread(mydlg.m_hWnd);
}