当前位置:编程学习 > C/C++ >>

C++ library series -- in the MFC multiple-thread environment, how to quit worker

 In the MFC environment, normally, thread should be launched with AfxBeginThread for taking usage of MFC multiple-thread mechanism; In such mechanism, those datastructures, such as AFX_MODULE_STATE, would be used by MFC framework to maintain related thread information. It runs well when threads, launched with AfxBeginThread, quit before the main thread, which is responsible for initializing C run-time, but if such main thread quit before any other thread launched by AfxBeginThread, the current application would crash.

  Such crash comes from the _afxThreadData (CThreadSlotData* _afxThreadData, which is defined in AFXTLS.cpp as global data structure) has been destructed while the main thread quits and it will invoke related function to clean up global data structures, including _afxThreadData definitely.
  Consequently, serious developer should prepare for such case (other worker thread quits before main thread).
  
  The reasonable resolve for such issue, would ensure any other threads should quit before the main thread. 
  
.h file 
  /////////////////////////////////////////////////////////////////////////////
// CSafeEnterLeaveThread thread
 
class CSafeEnterLeaveThread : public CWinThread
{
DECLARE_DYNCREATE(CSafeEnterLeaveThread)
protected:
CSafeEnterLeaveThread();           // protected constructor used by dynamic creation
 
// Attributes
public:
 
// Operations
public:
 
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSafeEnterLeaveThread)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
 
// Implementation
protected:
virtual ~CSafeEnterLeaveThread();
 
// Generated message map functions
//{{AFX_MSG(CSafeEnterLeaveThread)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
 
DECLARE_MESSAGE_MAP()
};
 
.cpp file 
/////////////////////////////////////////////////////////////////////////////
// CSafeEnterLeaveThread
 
IMPLEMENT_DYNCREATE(CSafeEnterLeaveThread, CWinThread)
 
CSafeEnterLeaveThread::CSafeEnterLeaveThread()
{
}
 
CSafeEnterLeaveThread::~CSafeEnterLeaveThread()
{
}
 
BOOL CSafeEnterLeaveThread::InitInstance()
{
// TODO:  perform and per-thread initialization here
ASSERT(this->m_hThread);
CMainApp::RegisterMFCThread(this->m_hThread);
return TRUE;
}
 
int CSafeEnterLeaveThread::ExitInstance()
{
// TODO:  perform any per-thread cleanup here
ASSERT(this->m_hThread);
CMainApp::UnRegisterMFCThread(this->m_hThread);
return CWinThread::ExitInstance();
}
 
BEGIN_MESSAGE_MAP(CSafeEnterLeaveThread, CWinThread)
//{{AFX_MSG_MAP(CSafeEnterLeaveThread)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
 
 
And in the CMainApp,
 
 
set<HANDLE> g_ThreadHandleSet;
HANDLE g_ThreadHandleArray[MAXIMUM_WAIT_OBJECTS];
CCriticalSection g_csGlobalData;
 
void CAccgbApp::CheckAllOtherMFCThreadsLeave()
{
int count = g_ThreadHandleSet.size();
if (count == 0) return;
set<HANDLE>::iterator it;
int idx = 0;
for (it = g_ThreadHandleSet.begin(); it != g_ThreadHandleSet.end() && idx < MAXIMUM_WAIT_OBJECTS; it++, idx++)
{
g_ThreadHandleArray[idx] = *it;
}
if (count > idx) count = idx;
 
::WaitForMultipleObjects(count, g_ThreadHandleArray, TRUE, INFINITE);
}
 
void CAccgbApp::CleanupGlobalData()
{
g_csGlobalData.Lock();
g_ThreadHandleSet.empty();
g_csGlobalData.Unlock();
}
 
BOOL CAccgbApp::RegisterMFCThread(HANDLE hThread)
{
if (hThread == NULL) return FALSE;
 
g_csGlobalData.Lock();
if (g_ThreadHandleSet.find(hThread) == g_ThreadHandleSet.end()) 
g_ThreadHandleSet.insert(hThread);
g_csGlobalData.Unlock();
 
return TRUE;
}
 
void CAccgbApp::UnRegisterMFCThread(HANDLE hThread)
{
if (hThread == NULL) return;
 
g_csGlobalData.Lock();
if (g_ThreadHandleSet.find(hThread) != g_ThreadHandleSet.end())
g_ThreadHandleSet.erase(hThread);
g_csGlobalData.Unlock();
}
摘自 唐亮的个人技术博客
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,