MFC里的OnIdle()

本文详细解析了MFC中CWinThread::Run()函数与OnIdle()的关系,OnIdle()在消息队列为空时被调用,用于处理空闲时间的任务。OnIdle()返回值决定了是否需要更多的空闲处理时间。通过示例展示了如何根据lCount参数执行不同优先级的任务,强调了在OnIdle中不应进行长时间任务,并需确保调用基类的OnIdle实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CWinThread::Run是程序生命的"活水源头"(侯捷:《深入浅出MFC》,函数存在于VC++ 6.0安装目录下提供的THRDCORE.CPP文件中):

 

// main running routine until thread exits
int CWinThread::Run()
{
 
ASSERT_VALID(this);

 
// for tracking the idle time state
 
BOOL bIdle = TRUE;
 
LONG lIdleCount = 0;

 
// acquire and dispatch messages until a WM_QUIT message is received.
 
for (;;)
 
{
  
// phase1: check to see if we can do idle work
  
while (bIdle && !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
  
{
   
// call OnIdle while in bIdle state
   
if (!OnIdle(lIdleCount++))
    
bIdle = FALSE; // assume "no idle" state
  
}

  
// phase2: pump messages while available
  
do
  
{
   
// pump message, but quit on WM_QUIT
   
if (!PumpMessage())
    
return ExitInstance();

   
// reset "no idle" state after pumping "normal" message
   
if (IsIdleMessage(&m_msgCur))
   
{
    
bIdle = TRUE;
    
lIdleCount = 0;
   
}

  
} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
 
}
 
ASSERT(FALSE); // not reachable
}

首先进行PeekMessage()未Peek到并且bIdleTrue则进行OnIdle()并且lIdleCount++,完成之后返回一个值,如果要接收更多的空闲处理时间,则返回非零值,bIdle仍旧为true,继续peek,若仍未peek到,则接着OnIdle,此时的lIdleCout1,可根据这个值进行不同优先级的任务设置,若peek到了则doPumpMessage;如果不需要更多的空闲时间则返回0bIdlefalse,此时do第二个循环,主要是lIdleCount0然后接着peek,下次空闲的时候将重新进行OnIdle的任务。

OnIdle具体如下:

CWinApp::OnIdle

virtual BOOL OnIdle( LONG lCount );

返回值:如果要接收更多的空闲处理时间,则返回非零值;如果不需要更多的空闲时间则返回0


参数:

lCount

该参数是一个计数值,当应用程序的消息队列为空,OnIdle函数被调用时,该计数值就增加1。每当一条新消息被处理时,该计数值就被复位为0。你可以使用lCount参数来确定应用程序不处理消息时空闲时间的相对长度。


说明:
如果要执行空闲时处理,则重载这个成员函数。当应用程序的消息队列为空时,OnIdle就在缺省的消息循环中被调用。你可以用重载函数来调用自己的后台空闲处理任务。
OnIdle
应返回0以表明不需要更多的空闲处理时间。当消息队列为空时,OnIdle每被调用一次lCount参数就增加,而每处理一条新消息lCount就被复位为0。你可以根据这个计数值调用不同的空闲处理例程。
下面总结了空闲循环处理:

1.

如果微软基础类库中的消息循环检查消息队列并发现没有未被处理的消息,它就为应用程序对象调用OnIdle函数,并将lCount参数设为0

2.

OnIdle执行一些处理,然后返回一个非零值,表示它还需要被调用,以进行进一步处理。

3.

消息循环再次检查消息队列。如果没有未处理的消息,则再次调用OnIdle,增加lCount参数。

4.

最后,OnIdle结束所有的空闲任务并返回0。这就告诉消息循环停止调用OnIdle直到在消息队列中接收到下一条消息为止,在那时,空闲循环将重新启动,而参数被设为0

因为只有在OnIdle返回之后应用程序才能处理用户输入,因此在OnIdle中不应进行较长的任务。

注意:
OnIdle
的缺省实现更新命令用户接口对象,如菜单项和工具条等,还实现了内部数据结构的清理。因此,如果你重载了OnIdle,你必须用重载版本中使用的lCount值来调用CWinApp::OnIdle。首先调用所有基类的空闲处理(即直到基类的OnIdle返回0)。如果你需要在基类处理完成之前进行一些工作,则应回顾基类的实现以在自己的工作期间选择一个合适的lCount值。

示例:
下面的两个例子演示了OnIdle的用法。

第一个例子处理两个空闲任务,用lCount参数来排列这些任务的优先权。第一个任务优先权较高,一旦可能你就应当执行此任务。第二个任务不十分重要,只有当用户输入有一个较长时间的间歇的时候才应执行此任务。注意其中对基类的OnIdle的调用。第二个例子管理着一组具有不同优先权的空闲任务。
BOOL CMyApp::OnIdle(LONG lCount)
{
  BOOL bMore = CWinApp::OnIdle(lCount);
  if (lCount == 0)
  {
    TRACE("App idle for short period of time/n");
    bMore = TRUE;
  }

  else if (lCount == 10)
  {
    TRACE("App idle for longer amount of time/n");
    bMore = TRUE;
  }

  else if (lCount == 100)
  {
    TRACE("App idle for even longer amount of time/n");
    bMore = TRUE;
  }

  else if (lCount == 1000)
  {
    TRACE("App idle for quite a long period of time/n");
    // bMore
没有被设为TRUE, 不在需要空闲
    //
重要:bMore 没有被设为 FALSE,因为 CWinApp::OnIdle可能还有其它空闲任务要完成。
  }
  return bMore; //
返回TRUE,只要还有其它空闲任务
}

第二个示例:
//
在这个例子中,有四个空闲循环任务,它们被赋予
//
不同的优先权,运行的机会不同:
// Task1
在空闲时总能运行,要求在框架处理它自己的空闲循环任务时没有消息在等候。(lCount01
// Task2
仅当Task1以及运行时才能运行,要求当Task1运行时没有消息在等候。
// Task3
Task4仅当Task1Task2都运行之后才能运行,
//
并且在此期间没有消息在等候。如果Task3能够运行,
//
Task4总是在Task3之后立即运行。
BOOL CMyApp::OnIdle(LONG lCount)
{
  //
在这个例子中,像多数应用程序一样,你应该让基类
  //
CWinApp::OnIdle在你试图进行任何附加的空闲循环
  //
过程之前完成它的处理。
  if (CWinApp::OnIdle(lCount)) return TRUE;
  //
基类的CWinApp::OnIdlelCount保留01给框架自己的
  //
空闲处理使用。如果你希望与框架平等地共享空闲处理
  //
时间,则应替换上面的if语句,直接调用CWinApp::OnIdle
  //
然后为lCount的值0/1加入一个case语句。首先应当研
  //
究基类的实现以理解你的空闲循环任务将会如何与框架的
  //
空闲循环处理竞争。
  switch (lCount)
  {
    case 2:
      Task1();
      return TRUE; //
下一次给 Task2 一个机会
    case 3:
      Task2();
      return TRUE; //
下一次给Task3Task4一个机会
    case 4:
      Task3();
      Task4();
      return FALSE; //
再次回到空闲循环任务
  }
  return FALSE;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值