解决上一节中延时函数占CPU使用率(达50%)的第二种方法是利用消息机制,通过API函数MsgWaitForMultipleObjects等待消息或超时的到来,从而避免使用循环检测使CPU占用率过高。完整的改进版Delay函数代码如下:

  1. procedure Delay(dwMilliseconds:DWORD);
  2. var
  3. endTick: DWORD;
  4. Event: THandle;
  5. begin
  6. Timer1.Enabled:=False;
  7. Event := CreateEvent(nil,False,False,nil);
  8. try
  9. endTick := GetTickCount+dwMilliseconds;
  10. while (dwMilliseconds > 0) and
  11. (MsgWaitForMultipleObjects(1, Event, False,
  12. dwMilliseconds, QS_ALLINPUT) = WAIT_OBJECT_0+1) do
  13. begin //还在延时期间且有输入消息则执行下面的分发消息
  14. Application.ProcessMessages;
  15. dwMilliseconds := endTick-GetTickcount;
  16. end;
  17. finally
  18. CloseHandle(Event); //关闭事件句柄,销毁事件对象
  19. end;
  20. Timer1.Enabled:=True;
  21. end;
  22. {用到的两个API函数}
  23. //***********************************************************************
  24. //函数:CreateEvent           //创建事件对象
  25. //参数:lpEventAttributes=nil //默认的安全符
  26. //      bManualReset=False    //自动复原:当事件被一个等待线程释放以后,
  27. //                            //系统将会自动将事件状态复原为无信号状态
  28. //      bInitialState=False   //指定事件对象的初始状态为无信号状态
  29. //      lpName=nil            //无名对象
  30. //返回值:事件对象句柄
  31. //***********************************************************************
  32. //**************************************************************************
  33. //函数:MsgWaitForMultipleObjects  //等待直到返回条件满足则立即返回
  34. //
  35. //返回条件:①指定(信号)事件对象(第二个参数)中的一个或所有(第三个参数)对象发出信号
  36. //(任意一个 ②指定的等待/超时时间(第四个参数)已到
  37. //满足即可) ③指定的消息(第五个参数)已抵达线程的输入队列
  38. //
  39. //参数:  nCount=1                      指定列表中的句柄数量为1
  40. //       pHandles=Event                指定对象句柄组合中的第一个元素为Event
  41. //       fWaitAll=False                任何对象发出信号即可
  42. //       dwMilliseconds=dwMilliseconds 等待的毫秒数为延时时间
  43. //       dwWakeMask=QS_ALLINPUT        标识特定的消息类型为消息队列的任何消息
  44. //返回值:WAIT_OBJECT_0+1(nCount)      有指定类型的消息到达
  45. //*************************************************************************

以下是MSDN中关于MsgWaitForMultipleObjects的一段说明:

The MsgWaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters an efficient wait state, using very little processor time while waiting for the conditions of the wait criteria to be met.

MsgWaitForMultipleObjects判断等待条件(即返回条件)是否满足,如果不满足,调用线程(在此即主线程)进入高效的等待状态:使用非常少的CPU时间来等候返回条件成立。

更多关于MsgWaitForMultipleObjects的介绍请参见http://msdn.microsoft.com/zh-cn/library/ms931460

测试

利用以上提到的三个函数:Sleep、Delay、改进的Delay,进行了一个简单的测试,结果截图如下:

(1) 使用Sleep

(2)使用Delay

(3)使用改进版Delay

分析总结:

①   Sleep函数挂起了程序,使界面和定时器都得不到响应,当然更不会占用CPU了。

②   Delay函数采用循环检测方式,虽然界面能得到及时响应,但在延时的5秒时间内CPU占用率达到了50%。

③   改进的Delay函数即能响应界面,CPU使用率也很低(几乎为0,只在有指定输入消息到达时才有1%)。

④   后两个函数对于窗体关闭消息也不能及时响应。

http://blog.csdn.net/tht2009/article/details/6685622

改进的延时函数Delay(使用MsgWaitForMultipleObjects等待消息或超时的到来)的更多相关文章

  1. flutter 延时函数delay Loading页面

    loading 页面 import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class Lo ...

  2. 【CC2530强化实训02】普通延时函数实现按键的长按与短按

    [CC2530强化实训02]普通延时函数实现按键的长按与短按 [题目要求]      用一个按键实现单击与双击的功能已经是很多嵌入式产品的常用手法.使用定时器的间隔定时来计算按键按下的时间是通用的做法 ...

  3. 5-3 Linux内核计时、延时函数与内核定时器【转】

    转自:http://www.xuebuyuan.com/510594.html 5-3 Linux内核计时.延时函数与内核定时器 计时 1. 内核时钟 1.1   内核通过定时器(timer)中断来跟 ...

  4. 【CC2530强化实训01】普通延时函数实现按键的长按与短按

    [CC2530强化实训01]普通延时函数实现按键的长按与短按 [题目要求]     用一个按键实现长按与短按的功能已经是很多嵌入式产品的常用手法.使用定时器的间隔定时来进行按键按下的时间是通用的做法, ...

  5. C# 延时函数 非Sleep

    1.示例: using System.Runtime.InteropServices; [DllImport("kernel32.dll")] static extern uint ...

  6. linux中内核延时函数 (转)

    第一类延时函数原型是:(忙等) void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsi ...

  7. 延时函数出错,volatile一例

    莫名其妙的错误.使用Systick做的延时. 初始化是这样的: //SysTick配置 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); if ...

  8. C# 非独占延时函数 非Sleep

    在C#窗口程序中,如果在主线程里调用Sleep,在Sleep完成之前, 界面呈现出假死状态,不能响应任何操作! 下边实现的是非独占性延时函数,延时过时中界面仍可响应消息: public static ...

  9. STC51几种简单的延时函数

    STC51几种简单的延时函数 ,* 延时子程序 * * * ********************************************************************** ...

随机推荐

  1. Javascript 拖拽的一些高级的应用——逐行分析代码,让你轻松了解拖拽的原理

    我们看看之前的拖拽在周围有东西的时候会出现什么问题? 在高级浏览器中不会有啥问题,我们放到IE7下面测试一下,问题就出来了.如图 我们可以很清楚的看到,文字都已经被选中了.那这个用户体验很不好,用起来 ...

  2. lex 和 yacc 的区别与联系

    lex负责词法解析,而yacc负责语法解析,其实说白了就是lex负责根据指定的正则表达式,将输入的字符串匹配成一个一个的token,同时允许用户将当前匹配到的字符串进行处理,并且允许返回一个标识当前t ...

  3. Android06-Fragment碎片

    ¨Fragment简介 ¨Fragment生命周期 ¨动态加载碎片Fragment Manager的使用   1.Fragment表示Activity中的一种行为或者一部分用户界面. 可以将Fragm ...

  4. setTimeout()与setInterval() 问题

    提示:setTimeout() 只执行 code 一次.如果要多次调用,请使用 setInterval() 或者让 code 自身再次调用 setTimeout(). 1. setInterval(c ...

  5. Android4.2中Phone的P-sensor的应用的分析。

    先说现象,现象就是来电话,接通电话,把手机屏幕靠近脸部,遮挡住P-sensor,屏幕变黑了,不遮挡住P-sensor,屏幕就点亮了.接着我们来看看代码流程. 步骤一: 在PhoneGlobals.ja ...

  6. HDU4551

    简单. /* 简单题 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include< ...

  7. POJ 2774 Long Long Message&&HDU 1403 Longest Common Substring&&COJ 1203

    后缀数组的买1送2题... HDU的那题数据实在是太水了,后来才发现在COJ和POJ上都是WA..原因在一点:在建立sa数组的时候里面的n应该是字符串长度+1....不懂可以去看罗大神的论文... 就 ...

  8. 第一章ASP.NET SignalR简介

    第一章ASP.NET SignalR简介 1.1概述: ASP.NET SignalR是微软新开发的类库,为的是帮助ASP.NET开发人员很方便地开发实时网络功能. SignalR允许服务器端和客户端 ...

  9. Asp.Net之三层架构

    三层架构之理论: 通常意义上讲的三层架构就是将整个项目应用划分为:表现层(UI),业务逻辑层(BLL),数据访问层(DAL).与传统的二层架构的区别在于在用户界面(UI)和数据库服务器之间,添加中间层 ...

  10. utf8+bom格式保存php curl乱码问题

    今天开发遇到一个php curl取数据乱码问题 不是gzip也不是编码设置问题 最后有一同事判断为utf8+bom保存数据原因,懒得深入了解utf8+bom,仅做记录 [root@centos5 ~] ...