Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

TaskTimer - An Object to Monitor Task Execution

0.00/5 (No votes)
8 Aug 2002 1  
An object that tracks a task's elapsed and remaining times, and execution state

Introduction

This article describes TaskTimer, a lightweight object that lets you easily track a task's elapsed and remaining times. Although there are various CodeProject articles that describe this functionality, this article separates the GUI aspect of progress display from the time computation. Because TaskTimer isn't part of any control or dialog, you can make use of its functionality in any user interface. TaskTimer also handles pausing and restarting the task being timed.

The sample application also demonstrates a couple of techniques that can help give your app a more professional look and feel:

  • Making a single threaded app responsive while performing a long task
  • Flicker free updating of progress text

How to Use TaskTimer

TaskTimer is easy to use! First, declare an instance of the object in your dialog.

TaskTimer   m_taskTimer;  // TaskTimer object used for timing

When you want to start timing, call the object's start() method.

// Start timing
m_taskTimer.start();

Every now and then, inform the object of your task's progress by calling its updateProgress() method.

// Update the task progress
nProgress = ...;
m_taskTimer.updateProgress (nProgress);

To determine the task's elapsed and estimated remaining times, just call the appropriate methods.

// Get elapsed and remaining times
long nElapsedTimeInSecs = m_taskTimer.getElapsedTime();
long nRemainingTimeInSecs = m_taskTimer.getRemainingTime();

To display a user friendly time interval instead of the number of seconds, use the alternate form of these methods.

// Display user friendly remaining time
CString strRemaining;
m_taskTimer.getRemainingTime (strRemaining);
SetDlgItemText (IDC_TIME_REMAINING, strRemaining);

To indicate that the task has been paused, resumed or stopped, call the appropriate method.

// User pressed "Pause"
m_taskTimer.pause();

TaskTimer API

The TaskTimer API contains functions to control timing, update progress, and retrieve timing and task state information.

// Control timing
void  start();      // start timing
void  pause();      // pause timing
void  resume();     // resume timing
void  stop();       // stop timing

// Update progress
void  update();                       // update elapsed time

void  updateProgress                  // update progress
        (long nProgress);

void  updateProgress                  // update progress and get
        (long   nProgress,            // remaining time
         long&  nRemainingTime);

// Retrieve timing
long  getProgress();                  // return current progress

long  getElapsedTime();               // get elapsed time

void  getElapsedTime                  // get elapsed time as components
        (long&  nHours,
         long&  nMinutes,
         long&  nSeconds);

void  getElapsedTime                  // get elapsed time as formatted string
        (CString& strElapsed);

long  getRemainingTime();             // get remaining time

void  getRemainingTime                // get remaining time as components
        (long&  nHours,
         long&  nMinutes,
         long&  nSeconds);

void  getRemainingTime                // get remaining time as formatted string
        (CString& strRemaining);

// Retrieve task state
bool  isRunning();                    // is task running?
bool  isPaused();                     // is task paused?
bool  isStopped();                    // is task stopped?

Responding to User Input While Performing a Long Task

To make a single threaded app respond to user input while performing a long task (e.g., within a pushbutton command handler), break up the task into a number subtasks and execute each subtask within a loop. After executing a subtask, pump the message queue. If you allow the user to cancel the task, check for cancellation after pumping the message queue, and take appropriate action.

void CTaskTimer_DemoDlg::OnStart()
{
  // Start processing
  m_taskTimer.start();

  // For each of the 10 "subtasks" ...
  for (long nTaskIterator=1; (nTaskIterator <= 10); nTaskIterator++) {

      // Execute a subtask and update the task progress
      doSomething();
      m_taskTimer.updateProgress (nTaskIterator * 10);

      // Pump the message queue
      MSG   msg;
      while (::PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
            AfxGetThread()->PumpMessage();

      // Quit if user cancelled
      if (m_bCancelled) {
          m_taskTimer.stop();
          break;
      }
  }
}

Flicker Free Updating of Progress Text

Although it's nice to provide your user with frequently updated progress information, constantly updating a static text control can produce annoying flickering. This simple function shows how to do away with flicker by only setting the control's text if it's changed.

void updateWindowText
  (CWnd*    pWnd,
   CString  strText)
{
  ASSERT (pWnd != NULL);
  CString strOldText;
  pWnd->GetWindowText (strOldText);
  if (strOldText != strText) {
      pWnd->SetWindowText (strText);
      pWnd->Invalidate();
      pWnd->UpdateWindow();
  }
}

Revision History

  • 7th August, 2002: Added methods update(), getElapsedTime (CString&) and getRemainingTime (CString&)
  • 21st April, 2002: Bug fix: stop() was not updating the current time
  • 16th April, 2002: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here