win下延时方法记录

记录一下

最开始采用的是

boost::this_thread::sleep(boost::posix_time::milliseconds(milli_seconds))


延迟80ms,结构实际延迟96-100ms之间,msdn也说明sleep的精度为16ms,延迟在20-60ms

下面3种方法:

boost::this_thread::interruptible_wait((milli_seconds));
boost::this_thread::sleep_for(boost::chrono::milliseconds(milli_seconds));
boost::this_thread::sleep_until(boost::chrono::system_clock::now() + boost::chrono::milliseconds(milli_seconds));

一样,误差都比较大,所以想到了下面一种方法:

while (true)
{
    if (timer.elapsed()*1000 >= milli_seconds)
        break;
    boost::this_thread::sleep(boost::posix_time::microseconds(500));
}

能精确到1ms,但是比较占用cpu
再仔细搜索,找到了这个链接:
https://stackoverflow.com/questions/85122/how-to-make-thread-sleep-less-than-a-millisecond-on-windows

里面主要有2个回答,一个说了为什么sleep延迟精确度比较低的原因,
另外一个提到了下面的方法:

#include <Windows.h>

static NTSTATUS(__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) = (NTSTATUS(__stdcall*)(BOOL, PLARGE_INTEGER)) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution");

static NTSTATUS(__stdcall *ZwSetTimerResolution)(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution) = (NTSTATUS(__stdcall*)(ULONG, BOOLEAN, PULONG)) GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwSetTimerResolution");


static void SleepShort(float milliseconds) {
    static bool once = true;
    if (once) {
        ULONG actualResolution;
        ZwSetTimerResolution(1, true, &actualResolution);
        once = false;
    }

    LARGE_INTEGER interval;
    interval.QuadPart = -1 * (int)(milliseconds * 10000.0f);
    NtDelayExecution(false, &interval);
}

里面用到了一些内核方法,可以采用下面链接中的方法
https://www.cnblogs.com/liff-engineer/archive/2013/06/06/3121432.html

上面这个链接里面还提到了其他几种精确延时,计时方法
,主要测试了timeSetEvent, 代码如下:

#include <Mmsystem.h>

#pragma comment(lib,"Winmm.lib")

void  CALLBACK TimeEvent(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
    printf("time ID is %d, started,dwUser is %d\n",uTimerID, dwUser);
    timeKillEvent(gtime_ID);
    return;
}

void StartEventTime(int millisec, DWORD_PTR duser)
{
    gtime_ID = timeSetEvent(millisec,1,(LPTIMECALLBACK)TimeEvent,(DWORD)this,TIME_PERIODIC);
    if(gtime_ID == NULL)
    {
        printf("time ID is not created\n");
        return;
    }
    return;
}

确实能精确一些,但还是精确不到1ms级别,也可能是我用的有问题
其他的计时方法,比如QueryPerformanceFrequency,有需要的话可以去看看

还有一种迂回的方法:

BOOLEAN nanosleep(LONGLONG ns){
    /* Declarations */
    HANDLE timer;   /* Timer handle */
    LARGE_INTEGER li;   /* Time defintion */
    /* Create timer */
    if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL)))
        return FALSE;
    /* Set timer properties */
    li.QuadPart = -ns;
    if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){
        CloseHandle(timer);
        return FALSE;
    }
    /* Start & wait for timer */
    WaitForSingleObject(timer, INFINITE);
    /* Clean resources */
    CloseHandle(timer);
    /* Slept without problems */
    return TRUE;
}

这个确实能获取精确的时间,但是比较重量级了
总的来说,没有比较理想的方法,暂时记录一下,后面看看吧

再加点内容,有个比较好的方法:

#include <windows.h>
#pragma comment(lib, "winmm.lib")

timeBeginPeriod(1);
Sleep(milli_seconds);
//boost::this_thread::sleep(boost::posix_time::milliseconds(milli_seconds));
timeEndPeriod(1);
send_packet();

timeBeginPeriod只针对Sleep函数或windows本身的时间操作,对于boost的sleep,无效

并且,调用timeBeginPeriod,能获取更高的时间精度,但是会降低系统性能,并且会阻止cpu电源管理进入省电模式

Call this function immediately before using timer services, and call the timeEndPeriod 
function immediately after you are finished using the timer services.
You must match each call to timeBeginPeriod with a call to timeEndPeriod, specifying the
 same minimum resolution in both calls. An application can make multiple timeBeginPeriod 
calls as long as each call is matched with a call to timeEndPeriod.
This function affects a global Windows setting. Windows uses the lowest value (that is, 
highest resolution) requested by any process. Setting a higher resolution can improve 
the accuracy of time-out intervals in wait functions. However, it can also reduce
 overall system performance, because the thread scheduler switches tasks more often. High
 resolutions can also prevent the CPU power management system from entering power-saving 
modes. Setting a higher resolution does not improve the accuracy of the high-resolution
 performance counter.

这是微软的文档:https://docs.microsoft.com/zh-cn/windows/desktop/api/timeapi/nf-timeapi-timebeginperiod

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值