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);
public:
bool Start(void);
bool Stop (void) { m_bStop = true; return true; }
bool Abort(void);
bool IsRunning() { return m_bIsRunning; };
bool IsSuccess() { return m_bSuccess; };
virtual bool Execute() = 0;
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;
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)
{
}
bool CConsumer::Start(void)
{
if(m_bIsRunning)
return false;
TCHAR CALLER[] = _T("CConsumer::Start");
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;
}
::DuplicateHandle (GetCurrentProcess(), m_pThread->m_hThread,
GetCurrentProcess(), &m_hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
SendMessageToObs(WM_MSG_START,NULL,NULL);
m_pThread->ResumeThread();
return true;
}
bool CConsumer::Abort(void)
{
if(!m_bIsRunning)
return true;
m_bStop = true;
Sleep(100);
TCHAR CALLER[] = _T("CConsumer::Abort");
::TerminateThread (m_hThread, 0);
DWORD dwExitCode;
::GetExitCodeThread (m_hThread, &dwExitCode);
if ( STILL_ACTIVE == dwExitCode )
{
Sleep(1000);
::TerminateThread (m_hThread, 0);
DWORD dwExitCode2;
::GetExitCodeThread (m_hThread, &dwExitCode2);
if ( STILL_ACTIVE == dwExitCode2 )
{
return false;
}
}
else
{
::CloseHandle (m_hThread);
}
SendMessageToObs(WM_MSG_ABORTED,NULL,NULL);
m_bIsRunning = false;
m_pThread = NULL;
m_hThread = NULL;
return true;
}
UINT CConsumer::LocalThreadFunc(void)
{
TCHAR CALLER[] = _T("CConsumer::LocalThreadFunc");
m_bSuccess = Execute();
m_bIsRunning = false;
SendMessageToObs(WM_MSG_ENDED,NULL,NULL);
if ( !m_bSuccess )
return 1;
return 0;
}
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 ---