繁体   English   中英

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

[英]Sleep C function in CodeBlocks (for Windows) doesn't work properly

我正在尝试使用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;
}

您正在以1ms的超时睡眠。 实际上,您正在放弃当前线程的时间片,默认情况下为1,56毫秒。 但是,如果您有像Visual Studio一样运行的WPF应用程序,它将设置为1ms。 睡眠返回的时间不会比您想睡觉的时间早,因此您将有效地等待多达2秒的睡眠时间的时间片。 如果使用像ETWController这样的探查器, 可以看到线程直接等待。

在此处输入图片说明

在那里,您看到我们有1004个上下文切换事件,它们平均等待1,6ms,而不是您预期的1ms。 OS调度程序如何影响您的睡眠时间还有很多。 最好的办法是测量。 例如,请参见SpinWait是危险的

例如,当我关闭所有强制使用1ms系统计时器的应用程序时,我将获得6,5s的睡眠时间! 为了检查真实的等待时间,我使用了带有高计时器的代码来打印真实的等待时间:

#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

您无法使用“ Sleep功能编写秒表。 它不用于计时。 它所做的所有事情都会导致一个线程将其剩余的时间片交给其他竞争的线程,从而允许它们执行。 无法保证线程将进入休眠的确切时间。 优先级较高的线程可能会抢占其执行时间。 根据文档

如果dwMilliseconds小于系统时钟的分辨率,则线程的睡眠时间可能少于指定的时间长度。 如果dwMilliseconds大于1个刻度但小于2个刻度,则等待时间可以介于1个和2个刻度之间,依此类推。

继续讨论如何提高睡眠间隔的准确性,但这也不是您想要的。 创建计时器更适合您的用途,例如使用SetTimer函数 指定一个回调函数,时间到时将通知您。 如果您需要一个非常精确的计时器,则可以使用多媒体计时器 此处提供教程。 不过,对于简单的秒表来说,可能是不必要的。

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

对操作系统的请求将尽力而为,不保证任何响应时间。 Windows在设计和优化时考虑到性能和吞吐量,适用于一般用途,而不是用于实时任务。 您的进程与其他也要引起操作系统注意的进程共享操作系统。 操作系统仅保证过程暂停至少将持续您要求的时间间隔 再加上循环处理的时间,意味着您将从此代码中获得不一致的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM