Click here to Skip to main content
Click here to Skip to main content

TaskTimer - an object to monitor task execution

, 8 Aug 2002
Rate this:
Please Sign up or sign in to vote.
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 (eg. 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

  • 7 August 2002
    Added methods update(), getElapsedTime (CString&) and getRemainingTime (CString&).

  • 21 April 2002
    Bug fix: stop() was not updating the current time.

  • 16 April 2002
    Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ravi Bhavnani
Technical Lead
Canada Canada
Ravi Bhavnani is an ardent fan of Microsoft technologies who loves building Windows apps, especially PIMs, system utilities, and things that go bump on the Internet. During his career, Ravi has developed expert systems, desktop imaging apps, marketing automation software, EDA tools, a platform to help people find, analyze and understand information, trading software for institutional investors and advanced data visualization solutions. He currently works for a company that provides enterprise workforce management solutions to large clients.
 
His interests include the .NET framework, reasoning systems, financial analysis and algorithmic trading, NLP, HCI and UI design. Ravi holds a BS in Physics and Math and an MS in Computer Science and was a Microsoft MVP (C++ and C# in 2006 and 2007). He is also the co-inventor of 2 patents on software security and generating data visualization dashboards. His claim to fame is that he crafted CodeProject's "joke" forum post icon.
 
Ravi's biggest fear is that one day he might actually get a life, although the chances of that happening seem extremely remote.
Follow on   Google+   LinkedIn

Comments and Discussions

 
QuestionHow can find Time Taken for an Thread PinmemberRenugopal24-May-05 0:31 
AnswerRe: How can find Time Taken for an Thread PinmemberRavi Bhavnani24-May-05 2:06 
GeneralWill make the task even longer. PinmemberWREY25-Mar-04 11:45 
GeneralRe: Will make the task even longer. PinmemberRavi Bhavnani25-Mar-04 12:03 
GeneralThere is always one more bug... PinmemberRavi Bhavnani18-Apr-02 12:25 
GeneralFixed PinmemberRavi Bhavnani22-Apr-02 3:22 
GeneralElegant PinmemberNorm Almond16-Apr-02 20:58 
GeneralRe: Elegant PinmemberRavi Bhavnani17-Apr-02 3:00 
GeneralGood! PinmemberNish [BusterBoy]16-Apr-02 13:55 
GeneralRe: Good! PinmemberRavi Bhavnani17-Apr-02 3:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 9 Aug 2002
Article Copyright 2002 by Ravi Bhavnani
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid