我在用MFC写Windows Sockets应用程序时,在服务器端我用如下函数创建工作线程
       //创建接受和处理客户端请求线程
DWORD dwThread;
m_hReqAndData=CreateThread(NULL,0,DirAndFileSizeServiceThread,this,0,&dwThread);
CloseHandle(m_hReqAndData); 

在工作线程运行到如下语句(红色部分)else//接受客户端数据
{
 //得到CClient类实例
  CClient *pClient=pServer->GetClient(allSockfd.fd_array[i]);
  if (pClient!=NULL)
  {
   /接受数据
    BOOL bRet=pClient->RecvData();
    //接受数据错误或者客户端关闭套接字
    if (FALSE==bRet)
    {
     //取出套接字
     SOCKET sTemp=allSockfd.fd_array[i];
    //从集合中删除
     FD_CLR(allSockfd.fd_array[i],&allSockfd);
    //从客户端管理链表中删除该客户端
    pServer->DeleteClient(sTemp);
     pClient=NULL;
    //更新界面信息
    pServer->ShowClinentNumInfo(allSockfd.fd_count);
    }
}
RecvData()函数中运行到m_pServer->ShowReqDirInfo(_T("请求根目录。"));  void CServerDlg::ShowReqDirInfo(CString strDir)//显示客户端请求目录
{
m_ctlTip.SetWindowText(strDir);
UpdateData(FALSE);
}
出现如下中断
void CWnd::AssertValid() const
{
if (m_hWnd == NULL)
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=NULL;
if(pMap)
{
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.
}
}
查了很多资料,还是搞不懂,我在主线程中向工作线程传递CServerDlg对象指针,在工作线程中调用CServerDlg的UpdataData()更新界面的时候就会出现错误。查了很多资料,还是迷雾一团,请各位高手指点一下,谢了……

解决方案 »

  1.   

    不要直接通过对话框指针调用UpdateData,在线程中给对话框发送消息吧
      

  2.   

    说得详细一点吧,就是在工作线程中 当需要更新界面的时候向主线程发送更新界面消息
    然后主线程调用UpdataData更新界面消息吗?
    工作线程中的m_pServer(CServerDlg指针对象)指针调用UpdataData为什么不可以呢?
      

  3.   

    可以在窗口映射一个消息,比如ON_MESSAGE(WM_UPDATEDATA, OnUpdateData),然后用SendMessage(WM_UPDATEDATA, FALSE)传消息给窗口,窗口的消息处理肯定是在UI线程里面,这时候可以用
      LRESULT CProtectPage::OnUpdateData(WPARAM wParam, LPARAM lParam)
      {
      UpdateData(wParam);
      return 0;
      }
    ONUpdateData是自定义的消息函数,WM_UPDATEDATA是自定义消息
    至于原因,MFC的窗口是线程相关的,每个窗口的HandleMap是储存在线程相关的堆栈里面的(thread-local-storage (TLS) ),线程环境都切换了当然线程堆栈的数据也就不一样了