CEvent m_begin;//启动线程事件
UINT TestThread(LPVOID pParam)//回调函数
{ CDatacollectDlg* pDlg=(CDatacollectDlg*)pParam;
//等待启动信号,如没有将一直等待下去
 if(::WaitForSingleObject(m_begin,INFINITE)== WAIT_OBJECT_0)
     {
         AfxMessageBox("Hello");
pDlg->OnSavedata();//存储数据函数
}
}
BOOL CDatacollectDlg::OnInitDialog()
{..............
   m_begin.ResetEvent();
}void CDatacollectDlg::OnRunButton()//开始运行函数
{...
 CDatacollectDlg::OnRun();//数据采集函数
AfxBeginThread(TestThread,GetSafeHwnd());//启动线程,即采集完数据后,启动存储线程进行数据保存!
m_begin.SetEvent();}
运行结果:弹出“hello"信息对话框,执行到此处就出现断言错误!系统文件D:\Microsoft Visual studio\vc98\MFC\SRC\wincore.cpp中的函数(下面)有错误:
void CWnd::AssertValid() const
{
return;     // null (unattached) windows are valid// check for special wnd??? values
ASSERT(HWND_TOP == NULL);       // same as desktop
if (m_hWnd == HWND_BOTTOM)
ASSERT(this == &CWnd::wndBottom);
else if (m_hWnd == HWND_TOPMOST)
ASSERT(this == &CWnd::wndTopMost);
else if (m_hWnd == HWND_NOTOPMOST)
ASSERT(this == &CWnd::wndNoTopMost);
else
{
// should be a normal window
ASSERT(::IsWindow(m_hWnd));// should also be in the permanent or temporary handle map
CHandleMap* pMap = afxMapHWND();
ASSERT(pMap != NULL); CObject* p;
ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
(p = pMap->LookupTemporary(m_hWnd)) != NULL);
ASSERT((CWnd*)p == this);   // must be us此行有错误! // Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
    // and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another.  The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
}
}
  
如何修改!请各位仁兄赐教!谢谢!甚急!

解决方案 »

  1.   

    一步一步来说,俺试验了你的代码,试验代码中pDlg->OnSavedata()的函数没有任何操作,
    是一个空函数,没有使用任何内容,没有任何错误发生。然后,我在pDlg->OnSavedata()函数中执行不涉及pDlg对象的操作,如TRACE, 简单的计算等,也没有发生错误。最后,假设在pDlg中增加一个成员变量,在pDlg->OnSavedata()对该变量进行
    操作,则断言异常。如果在pDlg->OnSavedata()中执行任何有关pDlg的窗口或子窗口对象的操作,如对控件内容取值,赋值,等,都发生断言异常。原因很简单,MFC对象不能在两个线程中间传递,这是一个很重要的规则。即使你向线程传递了一个handle,然后又在新线程中attach,但你仍然不能得到这个对象的所有正常的数据。按照ms的建议,你应该在线程中向窗口发送自定义消息,在窗口中处理该消息,完成pDlg->OnSavedata()功能。另外,你应该在异常发生的时候,观察堆栈窗口,来确定到底是什么引发了ASSERT,你就很清除发生什么了。再:俺的试验环境是VC6+SP5,可能和你的有差别,也许ms在SP5中能跨线程传递MFC对象了。