📄 thrdcore.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include <process.h> // for _beginthreadex and _endthreadex
#include <ddeml.h> // for MSGF_DDEMGR
#ifdef AFX_CORE1_SEG
#pragma code_seg(AFX_CORE1_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// Thread entry point
#ifdef _MT
struct _AFX_THREAD_STARTUP
{
// following are "in" parameters to thread startup
_AFX_THREAD_STATE* pThreadState; // thread state of parent thread
CWinThread* pThread; // CWinThread for new thread
DWORD dwCreateFlags; // thread creation flags
_PNH pfnNewHandler; // new handler for new thread
HANDLE hEvent; // event triggered after success/non-success
HANDLE hEvent2; // event triggered after thread is resumed
// strictly "out" -- set after hEvent is triggered
BOOL bError; // TRUE if error during startup
};
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();
#ifdef _AFXDLL
pThread->m_pModuleState = pModuleState;
#endif
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!!
TRACE0("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 invaid 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
}
#endif //_MT
CWinThread* AFXAPI AfxGetThread()
{
// check for current thread in module thread state
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
// if no CWinThread for the module, then use the global app
if (pThread == NULL)
pThread = AfxGetApp();
return pThread;
}
CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
int nPriority, UINT nStackSize, DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
pfnThreadProc;
pParam;
nPriority;
nStackSize;
dwCreateFlags;
lpSecurityAttrs;
return NULL;
#else
ASSERT(pfnThreadProc != NULL);
CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
ASSERT_VALID(pThread);
if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
lpSecurityAttrs))
{
pThread->Delete();
return NULL;
}
VERIFY(pThread->SetThreadPriority(nPriority));
if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1);
return pThread;
#endif //!_MT)
}
CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass,
int nPriority, UINT nStackSize, DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
pThreadClass;
nPriority;
nStackSize;
dwCreateFlags;
lpSecurityAttrs;
return NULL;
#else
ASSERT(pThreadClass != NULL);
ASSERT(pThreadClass->IsDerivedFrom(RUNTIME_CLASS(CWinThread)));
CWinThread* pThread = (CWinThread*)pThreadClass->CreateObject();
if (pThread == NULL)
AfxThrowMemoryException();
ASSERT_VALID(pThread);
pThread->m_pThreadParams = NULL;
if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
lpSecurityAttrs))
{
pThread->Delete();
return NULL;
}
VERIFY(pThread->SetThreadPriority(nPriority));
if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1);
return pThread;
#endif //!_MT
}
void AFXAPI AfxEndThread(UINT nExitCode, BOOL bDelete)
{
#ifndef _MT
nExitCode;
bDelete;
#else
// remove current CWinThread object from memory
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
if (pThread != NULL)
{
ASSERT_VALID(pThread);
ASSERT(pThread != AfxGetApp());
// cleanup OLE if required
if (pThread->m_lpfnOleTermOrFreeLib != NULL)
(*pThread->m_lpfnOleTermOrFreeLib)(TRUE, FALSE);
if (bDelete)
pThread->Delete();
pState->m_pCurrentWinThread = NULL;
}
// allow cleanup of any thread local objects
AfxTermThread();
// allow C-runtime to cleanup, and exit the thread
_endthreadex(nExitCode);
#endif //!_MT
}
/////////////////////////////////////////////////////////////////////////////
// Global functions for thread initialization and thread cleanup
LRESULT CALLBACK _AfxMsgFilterHook(int code, WPARAM wParam, LPARAM lParam);
void AFXAPI AfxInitThread()
{
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());
#ifndef _AFX_NO_CTL3D_SUPPORT
// intialize CTL3D for this thread
_AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
if (pCtl3dState->m_pfnAutoSubclass != NULL)
(*pCtl3dState->m_pfnAutoSubclass)(AfxGetInstanceHandle());
// allocate thread local _AFX_CTL3D_THREAD just for automatic termination
_AFX_CTL3D_THREAD* pTemp = _afxCtl3dThread;
pTemp; // avoid unused warning
#endif
}
}
extern CThreadSlotData* _afxThreadData;
void AFXAPI AfxTermThread(HINSTANCE hInstTerm)
{
try
{
#ifdef _DEBUG
// check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE1("Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
#endif
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
// cleanup thread local tooltip window
if (hInstTerm == NULL)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetDataNA();
if ((pThreadState != NULL) &&
(pThreadState->m_pToolTip != NULL))
{
pThreadState->m_pToolTip->DestroyWindow();
delete pThreadState->m_pToolTip;
pThreadState->m_pToolTip=NULL;
}
}
// cleanup the rest of the thread local data
if (_afxThreadData != NULL)
_afxThreadData->DeleteValues(hInstTerm, FALSE);
}
catch( CException* e )
{
e->Delete();
}
}
/////////////////////////////////////////////////////////////////////////////
// CWinThread construction
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
CWinThread::CWinThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam)
{
m_pfnThreadProc = pfnThreadProc;
m_pThreadParams = pParam;
CommonConstruct();
}
CWinThread::CWinThread()
{
m_pThreadParams = NULL;
m_pfnThreadProc = NULL;
CommonConstruct();
}
void CWinThread::CommonConstruct()
{
m_pMainWnd = NULL;
m_pActiveWnd = NULL;
// no HTHREAD until it is created
m_hThread = NULL;
m_nThreadID = 0;
// initialize message pump
#ifdef _DEBUG
m_nDisablePumpCount = 0;
#endif
m_msgCur.message = WM_NULL;
m_nMsgLast = WM_NULL;
::GetCursorPos(&m_ptCursorLast);
// most threads are deleted when not needed
m_bAutoDelete = TRUE;
// initialize OLE state
m_pMessageFilter = NULL;
m_lpfnOleTermOrFreeLib = NULL;
}
#ifdef AFX_TERM_SEG
#pragma code_seg(AFX_TERM_SEG)
#endif
CWinThread::~CWinThread()
{
// free thread object
if (m_hThread != NULL)
CloseHandle(m_hThread);
// cleanup module state
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
if (pState->m_pCurrentWinThread == this)
pState->m_pCurrentWinThread = NULL;
}
#ifdef AFX_CORE1_SEG
#pragma code_seg(AFX_CORE1_SEG)
#endif
BOOL CWinThread::CreateThread(DWORD dwCreateFlags, UINT nStackSize,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
dwCreateFlags;
nStackSize;
lpSecurityAttrs;
return FALSE;
#else
ASSERT(m_hThread == NULL); // already created?
// setup startup structure for thread initialization
_AFX_THREAD_STARTUP startup; memset(&startup, 0, sizeof(startup));
startup.pThreadState = AfxGetThreadState();
startup.pThread = this;
startup.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
startup.hEvent2 = ::CreateEvent(NULL, TRUE, FALSE, NULL);
startup.dwCreateFlags = dwCreateFlags;
if (startup.hEvent == NULL || startup.hEvent2 == NULL)
{
TRACE0("Warning: CreateEvent failed in CWinThread::CreateThread.\n");
if (startup.hEvent != NULL)
::CloseHandle(startup.hEvent);
if (startup.hEvent2 != NULL)
::CloseHandle(startup.hEvent2);
return FALSE;
}
// create the thread (it may or may not start to run)
m_hThread = (HANDLE)_beginthreadex(lpSecurityAttrs, nStackSize,
&_AfxThreadEntry, &startup, dwCreateFlags | CREATE_SUSPENDED, (UINT*)&m_nThreadID);
if (m_hThread == NULL)
return FALSE;
// start the thread just for MFC initialization
VERIFY(ResumeThread() != (DWORD)-1);
VERIFY(::WaitForSingleObject(startup.hEvent, INFINITE) == WAIT_OBJECT_0);
::CloseHandle(startup.hEvent);
// if created suspended, suspend it until resume thread wakes it up
if (dwCreateFlags & CREATE_SUSPENDED)
VERIFY(::SuspendThread(m_hThread) != (DWORD)-1);
// if error during startup, shut things down
if (startup.bError)
{
VERIFY(::WaitForSingleObject(m_hThread, INFINITE) == WAIT_OBJECT_0);
::CloseHandle(m_hThread);
m_hThread = NULL;
::CloseHandle(startup.hEvent2);
return FALSE;
}
// allow thread to continue, once resumed (it may already be resumed)
::SetEvent(startup.hEvent2);
return TRUE;
#endif //!_MT
}
void CWinThread::Delete()
{
// delete thread if it is auto-deleting
if (m_bAutoDelete)
delete this;
}
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -