TaskTimer - 监控任务执行的对象






4.38/5 (6投票s)
一个跟踪任务已用时间和剩余时间以及执行状态的对象
引言
本文介绍了 TaskTimer
,这是一个轻量级的对象,可让您轻松跟踪任务的已用时间和剩余时间。 尽管有各种 CodeProject 文章描述了此功能,但本文将进度显示的 GUI 方面与时间计算分开。 因为 TaskTimer
不是任何控件或对话框的一部分,所以您可以在任何用户界面中使用它的功能。 TaskTimer
还可以处理暂停和重新启动计时任务。
示例应用程序还演示了一些可以帮助您的应用程序具有更专业外观的技术
- 在执行长时间任务时使单线程应用程序保持响应
- 无闪烁更新进度文本
如何使用 TaskTimer
TaskTimer
易于使用! 首先,在您的对话框中声明该对象的一个实例。
TaskTimer m_taskTimer; // TaskTimer object used for timing
当您要开始计时时,调用该对象的 start()
方法。
// Start timing
m_taskTimer.start();
时不时地,通过调用其 updateProgress()
方法来告知该对象您的任务进度。
// Update the task progress
nProgress = ...;
m_taskTimer.updateProgress (nProgress);
要确定任务的已用时间和估计剩余时间,只需调用适当的方法。
// Get elapsed and remaining times
long nElapsedTimeInSecs = m_taskTimer.getElapsedTime();
long nRemainingTimeInSecs = m_taskTimer.getRemainingTime();
要显示用户友好的时间间隔而不是秒数,请使用这些方法的替代形式。
// Display user friendly remaining time
CString strRemaining;
m_taskTimer.getRemainingTime (strRemaining);
SetDlgItemText (IDC_TIME_REMAINING, strRemaining);
要指示任务已暂停、恢复或停止,请调用适当的方法。
// User pressed "Pause"
m_taskTimer.pause();
TaskTimer API
TaskTimer
API 包含控制计时、更新进度以及检索计时和任务状态信息的函数。
// 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?
在执行长时间任务时响应用户输入
为了使单线程应用程序在执行长时间任务时(例如,在 pushbutton 命令处理程序中)响应用户输入,请将任务分解为多个子任务,并在循环中执行每个子任务。 执行子任务后,泵送消息队列。 如果允许用户取消任务,请在泵送消息队列后检查取消,并采取适当的措施。
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;
}
}
}
无闪烁更新进度文本
尽管向您的用户提供经常更新的进度信息很好,但不断更新 static
文本控件可能会产生令人讨厌的闪烁。 这个简单的函数展示了如何通过仅在控件的文本发生更改时才设置它来消除闪烁。
void updateWindowText
(CWnd* pWnd,
CString strText)
{
ASSERT (pWnd != NULL);
CString strOldText;
pWnd->GetWindowText (strOldText);
if (strOldText != strText) {
pWnd->SetWindowText (strText);
pWnd->Invalidate();
pWnd->UpdateWindow();
}
}
修订历史
- 2002 年 8 月 7 日:添加了方法
update()
、getElapsedTime (CString&)
和getRemainingTime (CString&)
- 2002 年 4 月 21 日:错误修复:
stop()
未更新当前时间 - 2002 年 4 月 16 日:初始版本