mfc中主线程是WinMain还是CWinThread派生的应用程序类CWinApp中的线程
MFC通过类、宏进行了层层封装,搞的神秘兮兮,很容易绕晕。但好在大多数功能都有源代码,只要耐心看,总可以追溯。
首先,你的提问中,CWinThread的工作函数不是WinMain,而是Run。其次,如果讨论界定在MFC的标准主线程,那么这是很明确的,同样是Run函数。
CWinApp是MFC主线程的标准类,派生后的APP类,从InitInstance进入,之后进入了CWinApp类的Run:
int CWinApp::Run()
{
if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
{
// Not launched /Embedding or /Automation, but has no main window!
TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
AfxPostQuitMessage(0);
}
return CWinThread::Run();
}
这里调用了基类的Run函数,实际就是启动了主工作函数CWinThread::Run,这个函数的代码如下:
int CWinThread::Run()
{
ASSERT_VALID(this);
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}
// phase2: pump messages while available
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())
return ExitInstance();
// reset "no idle" state after pumping "normal" message
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}
ASSERT(FALSE); // not reachable
}
在MFC程序中,AfxWinMain实际上只是起到了“承接”的作用,串联了APP类的几个函数,并不是真正的工作函数。
进程调createthread(_startupWinMain),WinMain是主线程工作函数此函数创建子线程传给该线程工作函数按你分析是Run可我没看到子线程创建。我认为UI线程是主线程说明CWinApp没用createthread新建线程而为线程函数WinMain提供函数,WinMain是主线程它逻辑上是CWinApp工作函数,但其实不是,而是调用了它的几个成员。不知我理解对不对
我很奇怪,你说的createthread(_startupWinMain)是哪里来的?
MFC主线程的创建,实际使用的并不是API的函数CreateThread(虽然类中也有这个名字的函数),实际使用的,是C++提供的_beginthreadex函数创建的主线程,你百度一下这两个函数名,就可以知道它们的区别,不赘述了。
AfxBeginThread实际创建线程的代码是这样的:
m_hThread = (HANDLE)_beginthreadex(lpSecurityAttrs, nStackSize,
&_AfxThreadEntry, &startup, dwCreateFlags | CREATE_SUSPENDED, (UINT*)&m_nThreadID);
从这里可以看出,你所困惑的工作函数(这应该是说法上的差异,实际上MFC的线程和API的worker线程有所不同,我认为应该理解为“线程入口地址”更合适些)其实是_AfxThreadEntry,这是一个CWinThread类的支持函数(注意,不是成员),函数中完成了CWinThread初始化并实现了主窗口和主线程的绑定。
UI线程和传统的工作者线程是不同的,不能简单的理解为“工作函数”,因为UI线程实际是在worker线程基础上加上消息循环来实现的,而传统的工作函数,退化为”入口函数“,用来标记线程入口地址,实际的线程工作,是在消息环中处理的(APP的Run函数就是做这个的)。
我认为,你是在用传统worker线程的思维去理解MFC APP这样的UI线程造成的困惑,建议多看看UI线程方面的书籍,以更好的了解两者之间的差别。