• 改进的延时函数Delay(使用MsgWaitForMultipleObjects等待消息或超时的到来)


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

    [delphi] view plaincopyprint?
     
    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.   
    34. //**************************************************************************  
    35. //函数:MsgWaitForMultipleObjects  //等待直到返回条件满足则立即返回  
    36. //  
    37. //返回条件:①指定(信号)事件对象(第二个参数)中的一个或所有(第三个参数)对象发出信号  
    38. //(任意一个 ②指定的等待/超时时间(第四个参数)已到  
    39. //满足即可) ③指定的消息(第五个参数)已抵达线程的输入队列  
    40. //  
    41. //参数:  nCount=1                      指定列表中的句柄数量为1  
    42. //       pHandles=Event                指定对象句柄组合中的第一个元素为Event  
    43. //       fWaitAll=False                任何对象发出信号即可  
    44. //       dwMilliseconds=dwMilliseconds 等待的毫秒数为延时时间  
    45. //       dwWakeMask=QS_ALLINPUT        标识特定的消息类型为消息队列的任何消息  
    46. //返回值:WAIT_OBJECT_0+1(nCount)      有指定类型的消息到达  
    47. //*************************************************************************  

    以下是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

  • 相关阅读:
    Java生成json
    WinForm程序执行JS代码的多种方法以及使用WebBrowser与JS交互
    聚集索引和非聚集索引的区别
    如何编写函数才能提高代码质量
    前端程序员应该知道的15个 jQuery 小技巧
    FileShare枚举的使用(文件读写锁)
    ASP.NET MVC 数据库依赖缓存的实现
    C# 调用一个按钮的Click事件(利用反射)
    解决报错“超时时间已到。超时时间已到,但是尚未从池中获取连接”的方案
    关于浏览器URL中出现会话验证字符说明
  • 原文地址:https://www.cnblogs.com/findumars/p/5008558.html
Copyright © 2020-2023  润新知