[英]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.