原本都知道要用第三個class來處理這問題,但由於一直搞不懂第三個要怎麼做,所以就一直寫不出來。
目前參考的方法是使用一個Base class來當做傳遞Function pointer的介面,然後一個Template class來讓內層使用的class來使用function pointer,也避開兩個互相參照的class的交互參照之問題。
處理方式如下:
Class Processer (底下稱CP)有工作要麻煩 Class Thread (底下稱CT)處理,但是為了讓Main thread不要卡住,所以CT是另外開一個Thread來處理CP要求的工作。
然而當CT在處理工作時如遇到了例外,並無法立即讓CP知道目前的狀況,所以就需要讓CP開個管道(Function Pointer)來讓CT可以在遇到問題時,回來告知CP。
原本是打算用PostMessage()來達成這樣的需求,但是CT所在的dll可能會移植到別的平台上,所以如果使用PostMessage()來做的話,那麼在移植上,還需要去針對不同平台處理。
但是此時的需求只是要把CT遇到的狀況告知給CP,並由CP來告知使用者而已,所以不會造成CT的程序block,所以這邊就採用Class的 callback方式處理。(如果會發生blocking的話,那還是只能用Windows Message的方式處理會比較好處理,不然Thread也是可以。)
底下範例使用
Class CallBackBase:
class CCallBackBase
{
public:
CCallBackBase(){};
~CCallBackBase(){};
virtual bool Execute(void *Param) const = 0;
};
Template Class:
template < class cTarClass >
class CTestCallBack : public CCallBackBase
{
public:
typedef bool (cTarClass::*LPFUNC)(void *Param);
protected:
cTarClass *m_pTarClass;
LPFUNC m_pTarFunc;
public:
CTestCallBack() {
m_pTarClass = NULL;
};
~CTestCallBack() {};
void SetCallBack(cTarClass *cTarClassPtr, LPFUNC pFuncPtr){
m_pTarClass = cTarClassPtr;
m_pTarFunc = pFuncPtr;
};
virtual bool Execute(void *Param) const //Execute的參數要與function pointer一致是因為操作者是使用此介面來使用function pointer
{
if (m_pTarClass)
{
return (m_pTarClass->*m_pTarFunc)(Param);
}else{
::printf("ERROR: The call back funciton is not set!!");
}
return false;
};
};
Class Thread:
class CProcessThread
{
protected:
CCallBackBase *m_pCallBack;
HANDLE m_hThread;
public:
CProcessThread(){
m_pCallBack = NULL;
m_hThread = NULL;
};
~CProcessThread(){
if ( m_hThread != NULL ) {
DWORD dwExitCode = 0;
::TerminateThread(this->m_hThread, dwExitCode);
HANDLE hThread = this->m_hThread;
this->m_hThread = NULL;
::CloseHandle(hThread);
}
};
void StartProcessThread(void)
{
this->m_hThread = CreateThread( NULL, 0, ProcessThread, (LPVOID)this, 0, NULL);
};
void SetCallBack(CCallBackBase *pCallBack){
m_pCallBack = pCallBack;
};
protected:
static DWORD WINAPI ProcessThread(LPVOID lpParam)
{
CProcessThread *pcmxProcessThread = (CProcessThread*) lpParam;
return pcmxProcessThread->ProcessFunc();
};
DWORD ProcessFunc(void)
{
//Set callback data to upper class
m_pCallBack->Execute((void*) "This message is pass from ProcessThread::ProcessFunc() in Thread!!\n");
if ( m_hThread != NULL ) {
DWORD dwExitCode = 0;
::TerminateThread(this->m_hThread, dwExitCode);
HANDLE hThread = this->m_hThread;
this->m_hThread = NULL;
::CloseHandle(hThread);
}
return 0;
};
};
Class Process:
class CProcess
{
protected:
CTestCallBack<CProcess> m_CallBack;
CProcessThread m_ProcessThread;
public:
CProcess() {
m_CallBack.SetCallBack(this, &CProcess::CallBackShower);
m_ProcessThread.SetCallBack(&m_CallBack);
};
~CProcess() {};
void StartProcess(void)
{
m_ProcessThread.StartProcessThread();
};
bool CallBackShower(void *Param)
{
char szMsg[512];
strcpy(szMsg, (char*)Param);
::printf("The Pass message from call back is \nMsg = %s", szMsg);
return true;
};
};
Main program:
int _tmain(int argc, char* argv[])
{
CProcess Process;
Process.StartProcess();
system("pause");
return 0;
}
執行結果:
程式碼亂跑的問題再另外找解@@