在UI中创建一个对话框线程导致崩溃

时间:2010-09-16 15:15:16

标签: c++ multithreading

我尝试在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

感谢您查看此问题。

3 个答案:

答案 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处的示例队列