AfxBeginThread()干了什么?

来源:互联网 发布:五笔打字软件 编辑:程序博客网 时间:2024/04/27 19:09

 跟一跟AfxBeginThread的源码就可以很容易的发现,它调用了_beginthreadex,注意这家伙传递的可不是你传进去的函数函数指针,它传的是_AfxThreadEntry和一个_AFX_THREAD_STARTUP的结构,那我们的函数指针和参数呢??哦,原来都被封装到_AFX_THREAD_STARTUP里面了,那AfxThreadEntry这家伙想干什么。。

它调用了API CreateThread,传递的是_threadstartex和_ptiddata结构的参数,啊,原来上面的指针和参数又被打包成一个参数了,那最后调用的效果还会和原来的一样吗。。

原来在threadstartex中它又开始拆包工作了,最后和TCP/IP协议栈一样,拆出了我们的函数和参数

_endthreadex (
                ( (unsigned (__CLR_OR_STD_CALL *)(void *))(((_ptiddata)ptd)->_initaddr) )
                ( ((_ptiddata)ptd)->_initarg ) ) ;

这是threadex.c里面的代码。。这不是在拆包吗~~MFC的框架在模仿TCP/IP结构,这样做是。。?为了传递足够的信息!!保证线程的安全~~~

UINT APIENTRY _AfxThreadEntry(void* pParam)
{
 _AFX_THREAD_STARTUP* pStartup = (_AFX_THREAD_STARTUP*)pParam;
 ASSERT(pStartup != NULL);
 ASSERT(pStartup->pThreadState != NULL);
 ASSERT(pStartup->pThread != NULL);
 ASSERT(pStartup->hEvent != NULL);
 ASSERT(!pStartup->bError);

 CWinThread* pThread = pStartup->pThread;
 CWnd threadWnd;
 TRY
 {
  // inherit parent's module state
  _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  pThreadState->m_pModuleState = pStartup->pThreadState->m_pModuleState;

  // set current thread pointer for AfxGetThread
  AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  pThread->m_pModuleState = pModuleState;
  AFX_MODULE_THREAD_STATE* pState = pModuleState->m_thread;
  pState->m_pCurrentWinThread = pThread;

  // forced initialization of the thread
  AfxInitThread();

  // thread inherits app's main window if not already set
  CWinApp* pApp = AfxGetApp();
  if (pApp != NULL &&
   pThread->m_pMainWnd == NULL && pApp->m_pMainWnd->GetSafeHwnd() != NULL)
  {
   // just attach the HWND
   threadWnd.Attach(pApp->m_pMainWnd->m_hWnd);
   pThread->m_pMainWnd = &threadWnd;
  }
 }
 CATCH_ALL(e)
 {
  // Note: DELETE_EXCEPTION(e) not required.

  // exception happened during thread initialization!!
  TRACE(traceAppMsg, 0, "Warning: Error during thread initialization!\n");

  // set error flag and allow the creating thread to notice the error
  threadWnd.Detach();
  pStartup->bError = TRUE;
  VERIFY(::SetEvent(pStartup->hEvent));
  AfxEndThread((UINT)-1, FALSE);
  ASSERT(FALSE);  // unreachable
 }
 END_CATCH_ALL

 // pStartup is invlaid after the following
 // SetEvent (but hEvent2 is valid)
 HANDLE hEvent2 = pStartup->hEvent2;

 // allow the creating thread to return from CWinThread::CreateThread
 VERIFY(::SetEvent(pStartup->hEvent));

 // wait for thread to be resumed
 VERIFY(::WaitForSingleObject(hEvent2, INFINITE) == WAIT_OBJECT_0);
 ::CloseHandle(hEvent2);

 // first -- check for simple worker thread
 DWORD nResult = 0;
 if (pThread->m_pfnThreadProc != NULL)
 {
  nResult = (*pThread->m_pfnThreadProc)(pThread->m_pThreadParams);//注意!!这边就调用我们传递的函数啦
  ASSERT_VALID(pThread);
 }
 // else -- check for thread with message loop
 else if (!pThread->InitInstance())
 {
  ASSERT_VALID(pThread);
  nResult = pThread->ExitInstance();
 }
 else
 {
  // will stop after PostQuitMessage called
  ASSERT_VALID(pThread);
  nResult = pThread->Run();
 }

 // cleanup and shutdown the thread
 threadWnd.Detach();
 AfxEndThread(nResult);

 return 0;   // not reached
}

void AFXAPI AfxInitThread()//设置个消息钩子,hook之后它还想干什么?这个我就不知道了。。
{
 if (!afxContextIsDLL)
 {
  // set message filter proc
  _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
  ASSERT(pThreadState->m_hHookOldMsgFilter == NULL);
  pThreadState->m_hHookOldMsgFilter = ::SetWindowsHookEx(WH_MSGFILTER,
   _AfxMsgFilterHook, NULL, ::GetCurrentThreadId());
 }
}

上面的代码很清楚了,就一封包拆包过程,看了此文你就知道李久进讲的MFC线程是怎么来的了。。都是慢悠悠跟出来的~~

_AfxMsgFilterHook这家伙长这个样

LRESULT CALLBACK _AfxMsgFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
 CWinThread* pThread;
 if (afxContextIsDLL || (code < 0 && code != MSGF_DDEMGR) ||
  (pThread = AfxGetThread()) == NULL)
 {
  return ::CallNextHookEx(_afxThreadState->m_hHookOldMsgFilter,
   code, wParam, lParam);
 }
 ASSERT(pThread != NULL);
 return (LRESULT)pThread->ProcessMessageFilter(code, (LPMSG)lParam);
}

完了,一天都在跟MFC源码,再跟下回学校了,刚听说明天不加班,哈哈。。

BOOL CWinThread::ProcessMessageFilter(int code, LPMSG lpMsg)
{
 if (lpMsg == NULL)
  return FALSE;   // not handled

 CFrameWnd* pTopFrameWnd;
 CWnd* pMainWnd;
 CWnd* pMsgWnd;
 switch (code)
 {
 case MSGF_DDEMGR:
  // Unlike other WH_MSGFILTER codes, MSGF_DDEMGR should
  //  never call the next hook.
  // By returning FALSE, the message will be dispatched
  //  instead (the default behavior).
  return FALSE;

 case MSGF_MENU:
  pMsgWnd = CWnd::FromHandle(lpMsg->hwnd);
  if (pMsgWnd != NULL)
  {
   pTopFrameWnd = pMsgWnd->GetTopLevelFrame();
   if (pTopFrameWnd != NULL && pTopFrameWnd->IsTracking() &&
    pTopFrameWnd->m_bHelpMode)
   {
    pMainWnd = AfxGetMainWnd();
    if ((m_pMainWnd != NULL) && (IsEnterKey(lpMsg) || IsButtonUp(lpMsg)))
    {
     pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
     return TRUE;
    }
   }
  }
  // fall through...

 case MSGF_DIALOGBOX:    // handles message boxes as well.
  pMainWnd = AfxGetMainWnd();
  if (code == MSGF_DIALOGBOX && m_pActiveWnd != NULL &&
   lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST)
  {
   // need to translate messages for the in-place container
   _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
            ENSURE(pThreadState);

   if (pThreadState->m_bInMsgFilter)
    return FALSE;
   pThreadState->m_bInMsgFilter = TRUE;    // avoid reentering this code
   MSG msg = *lpMsg;
   if (m_pActiveWnd->IsWindowEnabled() && PreTranslateMessage(&msg))
   {
    pThreadState->m_bInMsgFilter = FALSE;
    return TRUE;
   }
   pThreadState->m_bInMsgFilter = FALSE;    // ok again
  }
  break;
 }

 return FALSE;   // default to not handled
}

头晕,回校~~

 

原创粉丝点击