CodeBlocks(适用于Windows)中的Sleep C功能无法正常工作

时间:2016-05-29 13:47:27

标签: c windows codeblocks sleep

我试图在C中使用秒表(对于Windows),代码似乎有效但睡眠功能的时间并不匹配实时。

进程返回0(0x0)执行时间:1.907 s 按任意键继续。

问题是执行时间大约是2秒,但它应该只有1秒..只是想知道我做错了什么因为Windows中的Sleep函数接受毫秒作为它应该工作的参数..这里是代码

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{

    int milliseconds=0;
    int seconds=0;
    int counter;

    for(counter=0;counter<1000;counter++) {

        Sleep(1);
        milliseconds = milliseconds + 1;
        printf("%d\n",milliseconds);

        if(milliseconds==1000) {
            seconds = seconds + 1;
            milliseconds = 0;
            printf("seconds: %d",seconds);
        }

    }

    return 0;
}

3 个答案:

答案 0 :(得分:1)

你正在睡觉,超时为1毫秒。实际上,您放弃了当前线程的时间片,默认为15,6ms。但是如果你有一个像Visual Studio一样运行的WPF应用程序,它将被设置为1ms。睡眠不会早于您想要睡觉的时间返回,因此您将有效地等待最多可达2s睡眠时间的倍数。 如果您使用像ETWController这样的分析器,您可以看到该线程直接等待。

enter image description here

在那里你看到我们有1004个上下文切换事件,它们平均等待1,6ms,而不是你预期的1ms。 OS调度程序如何影响您的睡眠时间,还有很多其他内容。最好的方法是衡量。请参阅示例SpinWait is dangerous

当我例如关闭所有强制执行1ms系统计时器的应用程序 睡眠时间为6.5秒! 为了检查真正的等待时间,我使用你的代码和highres定时器来打印真正的等待时间:

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <chrono>

int main()
{

    int milliseconds = 0;
    int seconds = 0;
    int counter;

    auto start = std::chrono::high_resolution_clock::now();

    for (counter = 0; counter<1000; counter++) {

        Sleep(1);
        milliseconds = milliseconds + 1;
        //printf("%d\n", milliseconds);

        if (milliseconds == 1000) {
            seconds = seconds + 1;
            milliseconds = 0;
            printf("\nseconds: %d", seconds);
        }

    }

    auto stop = std::chrono::high_resolution_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
    printf("Duration: %dms", ms);
    return 0;
}

这是输出:

ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com

Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 1.000 ms
seconds: 1
Duration: 1713ms

ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com

Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 15.625 ms

seconds: 1
Duration: 6593ms

答案 1 :(得分:1)

您无法使用Sleep功能编写秒表。它不适用于任何计时。它所做的就是让一个线程将剩余的时间片传递给其他竞争线程,从而允许它们执行。无法保证线程睡眠的准确时间。它的执行可能被更高优先级的线程抢占。根据{{​​3}}:

  

如果 dwMilliseconds 小于系统时钟的分辨率,则线程可能会睡眠时间少于指定的时间长度。如果 dwMilliseconds 大于一个刻度但小于2,则等待可以是一到两个刻度之间的任何位置,依此类推。

接着谈谈如何提高睡眠间隔的准确性,但这也不是你想要的。创建计时器更适合您的目的,例如使用the documentation。指定回调函数,时间结束后会通知您。如果您需要一个非常准确的计时器,您可以使用SetTimer function。教程可用multimedia timer。但是,对于简单的秒表来说可能是不必要的。

要获得时间计数并实现自己的计时工具,您可以调用GetTickCount函数。或使用here获得最大分辨率。 QueryPerformanceCounter会返回当前时间戳,您将其除以QueryPerformanceFrequency的结果。

答案 2 :(得分:0)

对操作系统的请求是在尽力而为的基础上处理的,没有任何响应时间保证。 Windows的设计和优化考虑了通用性能和吞吐量,而不是实时任务。您的进程与其他需要操作系统注意的进程共享操作系统。操作系统仅保证只要您请求给出或接受时钟滴答,过程暂停将至少持续 。加上循环的处理时间意味着您将从此代码获得不一致的结果。