为什么在工作者线程中直接销毁主线程的窗口会出错?debug差不多一整天,把我弄得差不多半死之后,我从网上得知,工作者线程中不能使用界面线程的指针或对象,直接销毁窗口!

举个例子,就是这种情况:

1
2
3
4
5
6
7
8
9
10
11
12
void CMainFrame::OnSomeAction()
 
{
	…
	m_pDlg->ShowWindow(SW_SHOW);
}
 
UINT ThreadProc(LPVOID lParam)
{
	…
	pDlg->DestroyWindow();//pDlg引用的m_pDlg
}

1
网上的解释如下,直接Copy,懒得写了!

可能初学者没有意识到,应用程序中创建的对象并非是整个进程共享的。在Windows应用程序体系中,对象是线程”私有”的(也就是调用对象方法不能超出线程边界)!也就是说,A线程创建了B对象,则B对象归A线程所有,A线程负责为B对象处理所有的消息(如果有的话)收发工作并交给B的消息处理函数或发到其他窗口对象去,线程结束时负责释放B对象。由于通常的应用程序创建对象及调用对象方法都是在主线程中进行的,因而不存在什么问题;但如果一个应用程序的多个线程需要操作同一个对象时,情况就会大不一样了。一个常见的多线程示例是:A线程(通常是主线程)创建一个对话框B,创建C线程负责处理后台工作,并将处理进展情况报告给B(例如在B上显示一些文字或图形信息或更新B的显示界面等)。初学者往往会犯这样的错误:将B对象的指针传递给C线程的线程函数,让C线程直接调用B对象的方法添加信息或更新显示界面。这样做对于一个简单的窗口类(如显示处理进度的对话框)而言,有时确实也成功了;但这要冒很大的潜在风险,那就是这种处理方法有时会莫名其妙的出错(通常是访问冲突导致的)!而对于一个复杂的类对象,采用类似的处理方法出现问题的可能性会大大增加,往往根本不能工作。

此问题的解决办法就是:向主线程发消息,由主线程自己处理!

写了个示例,演示了正确与错误的方法,大家可以下载看看

运行截图:

正确的方法:

right

错误的方法:

wrong

附件下载:

EggPainWorkerThread.rar