MFC对象不支持多线程操作。MSDN这样解释的:
In a multi-threaded application written using MFC, you should not pass MFC objects across thread boundaries. As a general rule, a thread should access only those MFC objects that it creates. Failure to do so may cause run-time problems including assertions or unexpected program behavior.
UpdateData()函数属于CDialog类的保护成员函数,在工作线程中不能使用UpdateData来更新主线程中的数据。更改界面的操作最好用主线程(界面线程),要想在子线程(工作线程)里执行界面线程的操作,可以通过向主线程发送消息来解决。
查了下资料,总结如下:
MFC对象不支持多线程操作,不能供多个线程进程使用,如果使用就可能产生错误。
子线程调用pDlg-> UpdateData(FALSE);时主线程会阻塞,而主线程是界面线程,Update必须由它完成,这样就形成死锁。
1、最通用的比较安全的解决方法:
主线程向子线程传递对象不安全,最好传递句柄;子线程中如果涉及对主线程的操作,最好利用PostMessage向主窗口发送自定义消息;在主窗口处理自定义消息,调用UpdateData(FALSE)。
方法2:
在线程进程里建立1个对话框地指针,在线程进程启动前把对话框地指针传递给线程进程里的指针对象或建立1个全局地对话框指针对象,在线程进程里调用。
方法3:
如果想要在线程进程中使用MFC,则要用AfxBeginThread创建线程进程。
方法4:
在线程进程中用如下方法获得你对话框指针:
CMyDlg* pDlg = (CMyDlg *)AfxGetApp()->m_pMainWnd;
pDlg->GetDlgItem(IDC_Edit1)->SetWindowText("OK");
方法5:
此个错误其实就为MFC在DEBUG模式下地保护性编程代码(Code)报错(有兴趣可以去读读编程代码(Code)),假如用Release模式编译及运行,不会出错,只不过在逻辑上存在风险。
这是我在使用管道进行进程操作时,遇到的一个问题,就是在线程里调用对话框的UpdateData函数总是出错。
//工作线程
DWORD WINAPI NewThread(LPVOID lParam)
{
CPipeDlg* pDlg=(CPipeDlg*)lParam;
=====================================================================================
=====================================================================================
pDlg->UpdateData(FALSE);//??????调试到这里有问题I
=====================================================================================
=====================================================================================
return 0;
}
运行如下所示,点击ping出现错误对话框。
将
pDlg->UpdateData(FALSE);
改为
pDlg->GetDlgItem(IDC_OUTPUT_INFO)->SetWindowText(pDlg->szOutPut);
程序运行后如图正常运行,当然最简单的方法是什么都不改,而是把编译及运行改为Release模式,结果一样正确。其他的方法我没有实验。