VC中的Sleep函数在延时应用中很好用,比如通信程序中,一方需等待另一方若干个毫秒后再处理,或者在死循环中,让出CPU不至于资源占用100%等等;
但是,在界面操作中不要使用Sleep函数,比如按钮事件中,不要调用这个函数,否则会出现意外的情况!!那么如何处理延时一段时间执行呢?使用定时器,将按钮事件中调用Sleep函数中的地方,改为启动一个一段时间执行后的定时器:SetTimer(定时器编号,毫秒数后执行,NULL);执行的动作放到定时器回调函数中执行,如果仅执行一次的,那么进到回调函数后首先将定时器关闭(即不是周期执行);
这样做的好处是,所有的“操作”(处理),都是在“本类”中。
另一个方案是启动一个线程:AfxBeginThread(处理回调函数,传递给回调函数的参数);但是也不建议使用!!因为,一般使用该函数都是这样使用,调用时:
AfxBeginThread(Fn, this); //this是“目前正在处理这个类”的指针
而在回调函数Fn中一般:
UINT Fn( LPVOID pParam )
{
CMyDlg *pDlg = (CMyDlg *)pParam;//切换到“正在处理”的类中
//其他处理
return 1L;
}
这涉及到RTTI,微软MFC在这方面做得不是太好(我在使用codeproject上的一些派生类控件就遇到了几个不解的问题,不知道是微软MFC的问题,还是那些派生类控件的问题),保守一点,使用定时器,可以避免这方面的弯路!
2. Sleep()的精度是可以保证的,如Sleep(4),能保证延时4个毫秒,但是不能用GetTickCOunt()函数来探测(最小精度15毫秒,不信自己验证),而是需使用:
#include
#include
//链接库
#pragma comment(lib, "Winmm.lib")
void main()
{
timeBeginPeriod(1);
Sleep(100);
int j=0;
//探测10次Sleep的延时
for(int i=0; i<10; i++)
{
DWORD s = timeGetTime();//开始时间(毫秒级)
//延时函数
Sleep(2);
//for (j=0; j<10000000; j++);//测算34~40毫秒,所以for循环每条指令为3~4个ns
DWORD e = timeGetTime();//结束时间(毫秒级)
printf("%d\n", e-s);//
}
}
小心,在一个复杂的工程中,使用windows多媒体库,有可能对原有系统的功能造成不稳定,如CPU占用率过高、破坏原有的定时频率等!!
2015_09_27编辑:在intel的x86上,还是采用“查询机器内硬件计数器工作频率”方式更好用:
2018_07_20编辑:使用时,要将该线程绑定到某个cpu上:
// TestCmd.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "TestCmd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
//将该线程绑定到CPU0上, 第二个参数为一个掩码,
DWORD_PTR mask=SetThreadAffinityMask(GetCurrentThread(), 0x0001);
printf("绑定到: %x\n", mask);
LARGE_INTEGER freq;
LARGE_INTEGER c1={0}, c2={0}, c={0};
//查询该机器本身的工作频率,并检查是否支持
BOOL b = QueryPerformanceFrequency(&freq);
if(b)
printf("频率 = %I64d\n", freq.QuadPart);
else
printf("QueryPerformanceFrequency 失败\n");
//下面检验Sleep(1)的精度
int i;
for (i=0; i<100; i++)
{
QueryPerformanceCounter(&c1);
c.QuadPart = c1.QuadPart - c2.QuadPart;
printf("%I64d, %.5fs\n",
c.QuadPart, //计数器差
c.QuadPart/(double)freq.QuadPart //周期值,单位:秒
);
Sleep(1);
c2 = c1;
}
getchar();
}
return nRetCode;
}