TThreadCtrlDlg

written by: lore
email: lore at newty dot de
home: www.newty.de
last updated: 25.07.00

Download Example Project

Overview

Thread-Control dialog with progress-gauge/texts, cancel/bkgnd-buttons and timer-powered callback of a user-specified function. The dialog can be used modal or non-modal.

Details

The thread-control dialog is used to control an additional thread. You start your thread-function and supply a pointer to an instance of this class in the argument list. In your thread-function you call setStopFlag(bool* flag) and supply the pointer to a flag. This flag is set when the user chooses to stop the thread. So you have got to check this flag periodically in your thread-function. Call shutDown() as the last statement in your thread-function.
Note: ALL actions with the dialog, including the try to close it, only result in setting the stop-flag. The dialog is always closed using shutDown()!.

More Details

How to Use

The following code is an excerpt from the projectīs file main.cpp and shows how to execute some calculation in an additional thread using the thread-control dialog to control execution. There are three functions: CmThreadDemo() which is called when the menu-item Thread Demo is selected by the user, threadFunc() which contains the code you want to be executed in the additional thread and dispState() which is the callback-function and is used to display information about the actual progress. For this example the callback-function could have been integrated in the dialog but when you want to display more specific informations youīll notice the flexibility of this concept.

Now, how does it work: First we new an instance of TThreadCtrlDlg, set itīs text-field(s) and supply the pointer to the callback-function. Then we start a new thread using _beginthread(threadFunc, 4096, argList). threadFunc is a pointer to our callback-function, i.g. just the name of the function. argList will be passed as a void-pointer to our callback-function each time it is called. Now our additional thread is running and in the meanwhile we call Execute() for modal execution of the thread-control dialog in the main-thread. The Execute()-function finishes when shutDown() gets called at the end of the thread-function. Now the return-value will be checked and if the user has choosen to execute in the background, we just do so by repeating all the commands from above with just the slight difference that we do execute the dialog none-modal by calling Create() instead of Execute(). Thatīs it.


   /****************************************************/
   //
   //  usage of thread-control-dialog TThreadCtrlDlg
   //


#include <process.h>             // due to: _beginthread()
#include "threadCtrlDlg.h"

////////////////////////////////////////////////////////////////////////////////////////
// function which is to be called by the thread-control dialog periodically
void dispState(void* _dialog)
{
   TThreadCtrlDlg* dialog = (TThreadCtrlDlg*) _dialog;   // explicit typecast
   dialog->setGauge(dialog->progress);                   // just set the gauge
}


////////////////////////////////////////////////////////////////////////////////////////
// thread-function: this functions contains the code you want to be executed in an
// additional thread.
void threadFunc(void* _dialog)
{
   TThreadCtrlDlg* dialog = (TThreadCtrlDlg*) _dialog;   // explicit typecast


   // pass a pointer to the stop-flag to the dialog
   bool stop=false;
   dialog->setStopFlag(&stop);



   // calculate something - note: this loops runs 100 times
   do
   {
      Sleep(100);           // calculation is emulated by a sleep-command which stops the thread for 0.1s
      dialog->progress++;   // increment progress-counter

      if(stop)              // check stop-flag and if true: immediately leave the loop
         break;

   } while(dialog->progress<100);


   // end dialog and exit the thread by exiting the function
   dialog->shutDown();
}



/***********************************************************************************************************/
// function shows how to execute threadFunc() in an additional thread.
void mainWnd::CmThreadDemo()
{
// I. example how to execute modal

   // a) instantiate a thread-control dialog with buttons
   TThreadCtrlDlg* pCtrlDlg = new TThreadCtrlDlg(this, "testing thread-control dialog",  IDD_DIALOG, font, true);


   // b) set first text-field and callback-function
   pCtrlDlg->setText1("performing modal");
   pCtrlDlg->setCallbackFunc(dispState, (void*) pCtrlDlg, /* call every 0.25 seconds = */250);


   // c) start additional thread using _beginthread(): the function 'threadFunc' will be called and the pointer
   //    'pCtrlDlg' will be passed to it as a void-pointer.
   _beginthread(/*pointer to thread-function*/threadFunc, 4096, /*pointer to argument-list*/void*) pCtrlDlg);


   // d) execute thread-control dialog modal. note: the additional thread is already running at this moment
   int returnValue=pCtrlDlg->Execute();
   int actualState=pCtrlDlg->progress; // remember dialogīs state for eventual later use

   // e) delete thread-control dialog
   delete pCtrlDlg;



 // II. example how to execute none-modal - note: this code is executed if the user hits the 'background'-button
 //     during the modal execution in I.
   if(returnValue==ID_BKGND)
   {
      // a) instantiate a thread-control dialog without buttons
      //    IMPORTANT: do not use the dialog twice! it is not implemented for this kind of use. you would cause
      //               a lot of problems otherwise: one prob is, that the Execute()-function is left before(!)
      //               the function ShutDown() is left in your additional thread. thus you may come up to this
      //               point here while there is still some code executed in your additional thread.
      TThreadCtrlDlg* pCtrlDlg = new TThreadCtrlDlg(this, "testing thread-control dialog",  IDD_DIALOG, font);


      // b) set first and second text-field and set callback-function
      pCtrlDlg->setText1("performing in the background ...");
      pCtrlDlg->setText2("... and without any buttons");
      pCtrlDlg->setCallbackFunc(dispState, (void*) pCtrlDlg, /* call every 0.25 seconds = */250);


      // c) start additional thread - note: the same thread-function is used as for modal execution.
      _beginthread(threadFunc, 4096, (void*) pCtrlDlg);


      // d) set flag, actual state (progress) and create dialog-window
      pCtrlDlg->SetFlag(wfDeleteOnClose);             // dialog will be deleted when it is closed
      pCtrlDlg->progress=actualState;
      pCtrlDlg->Create();
   }
}
Download Example Project