RxClient *msgRx; msgRx = new RxClient; void rxThreadProc( ComThreadArg *cta ) { ComThread thread( cta, quitMessages[ QM_MASTER ] ); TRY DvrApi driver = *cta->pDvr; // Private driver. if( !registerMsgRx( &driver, cta->abortEvent )) // Register msgRx. return; while(1) { msg = msgRx->getMsg( msg, RCGM_NORMAL ); ... Process application-specific message ....... } ENDTRY catch( ThrowAbort abort ) { delete msgRx; /* This must be done before calling MessageBox, which * gives the UI thread a chance to quit and remove the program before we get * a chance to do this. It is needed to release resources and to route messages * back to their previous recipients. */ msgRx = 0; thread.quitFor( quitMessages[ abort.abortType ] ); userMessage( 0, MB_ICONERROR + MB_OK, quitMessages[ abort.abortType ]); } if( msgRx != 0 ) delete msgRx; } HANDLE rxAbort = 0; ComThreadApi rxThread; rxThread.start( rxThreadProc, &comDvr, rxAbort ); Library code. enum { MB_UNINIT, MB_DEAD, MB_BORN, MB_UNBORN, MB_KILL }; // mailbox values. typedef struct { DvrApi *pDvr; int *pMailbox; char **pQuitFor; HANDLE abortEvent; long extra; /* Optional application information, typically a pointer to data, which must be global to be passed between threads. Unless the child thread specifically uses it, this is not needed and can default to 0. */ } ComThreadArg; class CLASS_DECLSPEC ComThreadApi { ComThreadArg arg; public: int mailbox; char *quitFor; ComThreadApi( void ) { mailbox = MB_UNINIT; } bool isInit( void ) { return mailbox != MB_UNINIT; } bool isActive( void ) { return mailbox > MB_DEAD; } bool isRunning( void ) { return mailbox == MB_BORN; } bool isInLimbo( void ) { return mailbox > MB_BORN; } void start( void (*func)( ComThreadArg * ), DvrApi *dvr, HANDLE abortEvent, long extra = 0 ) { arg.pDvr = dvr; arg.pMailbox = &mailbox; arg.pQuitFor = &quitFor; arg.abortEvent = abortEvent; mailbox = MB_UNBORN; arg.extra = extra; _beginthread( (void (__cdecl *)(void *))func, 0, (void *)&arg ); } void kill( HANDLE abort ); }; class ComThread { ComThreadArg *cta; public: ComThread( ComThreadArg *ctap, char *defaultQuitFor ) { cta = ctap; // Copy for class functions. *ctap->pQuitFor = defaultQuitFor; *ctap->pMailbox = MB_BORN; } ~ComThread( void ) { *cta->pMailbox = MB_DEAD; _endthread(); } int& mailbox( void ) { return *cta->pMailbox; } void quitFor( char *reason ) { *cta->pQuitFor = reason; } };