[C++/MFC] : Use a Thread Delegator for your threads





0/5 (0 vote)
I always use a somewhat different approach, here is a class"consumer" that has embedded the thread call in a member function,the member function runs a virtual call, hence the derived classesmay implement functionality as well as passing arguments asmember data of the class. Maybe you're...
I always use a somewhat different approach, here is a class
"consumer" that has embedded the thread call in a member function,
the member function runs a virtual call, hence the derived classes
may implement functionality as well as passing arguments as
member data of the class. Maybe you're interested to add such a method
to embed a thread call in a class to the spectrum of alternatives:
--- header ---
#ifndef CONSUMER_H #define CONSUMER_H #include <afx.h> #include <afxwin.h> #include <set> using namespace std; typedef set<CWnd*> ObserverListConsumerDef; class CConsumer { public: CConsumer(void); virtual ~CConsumer(void); // Thread Interface public: bool Start(void); // Start the thread bool Stop (void) { m_bStop = true; return true; } // Stop the thread bool Abort(void); // Stop the thread (brute force kill it) bool IsRunning() { return m_bIsRunning; }; // Is the thread running bool IsSuccess() { return m_bSuccess; }; // Was the run successful ? virtual bool Execute() = 0; // Override to provide functionality // the thread itself protected: static UINT ThreadFunc(LPVOID pVoid) { return( ((CConsumer*) pVoid)->LocalThreadFunc() ); } UINT LocalThreadFunc(void); bool m_bIsRunning; bool m_bSuccess; bool m_bStop; CWinThread* m_pThread; HANDLE m_hThread; // Observer Windows public: void SetObserver(CWnd *pWnd); void DelObserver(CWnd *pWnd); protected: ObserverListConsumerDef m_ObserverList; void SendMessageToObs(UINT nMsg, WPARAM wP, LPARAM lP); }; #endif // ! defined (CONSUMER_H)--- header --- --- body ---
#include "StdAfx.h" #include "Consumer.h" #ifndef THREADMESSAGES_H #define THREADMESSAGES_H #define WM_MSG_START (WM_USER + 0x0101) #define WM_MSG_ABORTED (WM_USER + 0x0102) #define WM_MSG_ENDED (WM_USER + 0x0103) #define WM_MSG_PROGRESS (WM_USER + 0x0104) #define WM_MSG_DATA (WM_USER + 0x0105) #endif // ! defined (THREADMESSAGES_H) CConsumer::CConsumer(void) { m_bIsRunning = false; m_bSuccess = false; m_bStop = false; m_pThread = NULL; m_hThread = NULL; } CConsumer::~CConsumer(void) { } // Thread Interface // Start the thread bool CConsumer::Start(void) { if(m_bIsRunning) return false; TCHAR CALLER[] = _T("CConsumer::Start"); // reset the success flag m_bSuccess = false; m_bStop = false; m_bIsRunning = true; m_pThread = AfxBeginThread ((AFX_THREADPROC) ThreadFunc, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); if(!m_pThread) { m_bIsRunning = false; m_pThread = NULL; m_hThread = NULL; return false; } // get the thread handle ::DuplicateHandle (GetCurrentProcess(), m_pThread->m_hThread, GetCurrentProcess(), &m_hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); SendMessageToObs(WM_MSG_START,NULL,NULL); // resume the suspended thread m_pThread->ResumeThread(); return true; } // Stop the thread bool CConsumer::Abort(void) { if(!m_bIsRunning) return true; m_bStop = true; Sleep(100); TCHAR CALLER[] = _T("CConsumer::Abort"); // Terminate brutally the thread. ::TerminateThread (m_hThread, 0); // Check the thread termination DWORD dwExitCode; ::GetExitCodeThread (m_hThread, &dwExitCode); if ( STILL_ACTIVE == dwExitCode ) { // The thread is still running. Sleep(1000); // Try again to kill it ::TerminateThread (m_hThread, 0); // Check the thread termination DWORD dwExitCode2; ::GetExitCodeThread (m_hThread, &dwExitCode2); if ( STILL_ACTIVE == dwExitCode2 ) { return false; } } else { // The thread has terminated. Close the thread handle. ::CloseHandle (m_hThread); } SendMessageToObs(WM_MSG_ABORTED,NULL,NULL); m_bIsRunning = false; m_pThread = NULL; m_hThread = NULL; return true; } // the thread itself UINT CConsumer::LocalThreadFunc(void) { TCHAR CALLER[] = _T("CConsumer::LocalThreadFunc"); // do work m_bSuccess = Execute(); m_bIsRunning = false; SendMessageToObs(WM_MSG_ENDED,NULL,NULL); if ( !m_bSuccess ) return 1; // error during simulation return 0; // success } void CConsumer::SetObserver(CWnd *pWnd) { m_ObserverList.insert(pWnd); } void CConsumer::DelObserver(CWnd *pWnd) { ObserverListConsumerDef::iterator it = m_ObserverList.find(pWnd); if ( it != m_ObserverList.end() ) m_ObserverList.erase(it); } void CConsumer::SendMessageToObs(UINT nMsg, WPARAM wP, LPARAM lP) { CWnd* pWnd = NULL; ObserverListConsumerDef::iterator it = m_ObserverList.begin(); while ( it != m_ObserverList.end() ) { pWnd = NULL; pWnd = *it; if (pWnd) pWnd->SendMessage(nMsg, wP, lP); it++; } }--- body ---