Click here to Skip to main content
Click here to Skip to main content
Alternative Tip/Trick

Tagged as

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

, 19 Oct 2010 CPOL
Rate this:
Please Sign up or sign in to 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 ---

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

federico.strati
Software Developer (Senior)
Italy Italy
Senior Software Developer in C/C++ and Oracle.
Ex-physicist holding a Ph.D. on x-ray lasers.

Comments and Discussions

 
GeneralClass is good, no issues regardning that. But it is not flex... PinmemberAjay Vijayvargiya19-Oct-10 2:05 
GeneralYes, it is more complex in the base class stated, but it is ... Pinmemberfederico.strati19-Oct-10 1:30 
GeneralAnd how do you use it? I assume it is more complex than Crea... PinmemberAjay Vijayvargiya19-Oct-10 0:51 
And how do you use it?
I assume it is more complex than CreateThread, AfxBeginThread.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141216.1 | Last Updated 19 Oct 2010
Article Copyright 2010 by federico.strati
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid