程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ library series -- in the MFC multiple-thread environment

C++ library series -- in the MFC multiple-thread environment

編輯:C++入門知識

 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(); } 摘自 唐亮的個人技術博客

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved