我尝试在UI线程(CWinThread)中创建一个对话框。 但是,当调用CDialog :: Create()时它会崩溃。 我已经验证了之前的实现,在非线程模式下成功创建了对话框。
这里有没有大师知道在CWinThread中创建对话的崩溃原因?
没有线程:
class CProduction : public CDialog{
...
}
class CScrollProductionView : public CScrollView{
CProduction *m_pProduction;
...
}
void CScrollProductionView::OnInitialUpdate(){
m_pProduction = new CProduction(0, *m_pVisionAdapter);
m_pProduction->Create(IDD_DLG_PROD, this); //--> created dialog successfully
m_pProduction->ShowWindow(SW_SHOW);
}
实施UI线程:
class CProduction : public CDialog{
...
}
class CScrollProductionView : public CScrollView{
CProductionThread* m_pProdThread;
...
}
class CProductionThread : public CWinThread{
CProduction *m_pProduction;
...
}
void CScrollProductionView::OnInitialUpdate(){
m_pProdThread->PostThreadMessage(WM_INITPRODTHREADMESSAGE, PROD_INIT, (LPARAM)m_pVisionAdapter);
m_pProdThread->PostThreadMessage(WM_INITPRODTHREADMESSAGE, PROD_CREATE_DLG, (LPARAM)this);
}
void CProductionThread::InitMessageHandler(WPARAM wParam, LPARAM lParam)
{
printf("Receiving InitMessageHandler msg %d\n", (UINT)wParam);
switch(wParam)
{
case PROD_INIT:
{
CVisionAdapter* pAdapter = (CVisionAdapter*)lParam;
m_pProduction = new CProduction(NULL, *pAdapter);
}
break;
case PROD_CREATE_DLG:
{
CScrollProductionView* pView = (CScrollProductionView*)lParam;
m_pProduction->Create(IDD_DLG_PROD, pView); //--> Crash here
m_pProduction->ShowWindow(SW_SHOW);
}
break;
default:
break;
}
}
错误讯息:
调试断言失败! ..
文件:.... wincore.cpp
行:9906
感谢您查看此问题。
答案 0 :(得分:3)
尝试不创建CWinThread,而不是创建工作线程,如果你在类之间有很多通信,比如传递对象指针,字符串等。
如果通过消息处理更新GUI,您会感到头疼。
答案 1 :(得分:0)
崩溃是由MFC在创建期间引用无效窗口句柄(作为父项传入)引起的。
作为一般规则,线程可以访问 仅创建它的MFC对象。这个 是因为暂时的和永久的 Windows句柄映射保留在线程中 本地存储有助于维护 防止同时访问 来自多个线程。
http://msdn.microsoft.com/en-us/library/h14y172e(VS.71).aspx
MSDN中说明的简单修复涉及将代码更改为
...
m_pProdThread->PostThreadMessage(WM_INITPRODTHREADMESSAGE, PROD_CREATE_DLG, (LPARAM)this->GetSafeHwnd());
...
CScrollProductionView* pView = (CScrollProductionView*)CScrollProductionView::FromHandle((HWND)lParam);
m_pProduction->Create(IDD_DLG_PROD, pView);
m_pProduction->ShowWindow(SW_SHOW);
修改:
修复了msdn。
答案 2 :(得分:0)
我怀疑问题是在处理CProduction
消息时尚未创建PROD_CREATE_DLG
对象。这可能是因为使用了PostThreadMessage
。使用PostThreadMessage
充满了问题。特别是,消息可能会丢失,因此线程永远不会看到PROD_INIT
消息。
在单线程代码中,您可以在CProduction
调用之前创建Create
对象。为什么不在多线程代码中执行相同操作?
如果您真的想使用Windows消息在线程之间进行通信,我会创建一个“仅消息”窗口(请参阅http://msdn.microsoft.com/en-us/library/ms632599.aspx#message_only),因为窗口消息不会像以下那样丢失线程消息。
或者,使用线程安全队列在线程之间传递自定义消息,例如http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html处的示例队列