簡體   English   中英

我的毫秒秒表似乎很慢

[英]My millisecond stopwatch seems to be slow

我很無聊,所以我用 C++ 寫了一個快速的毫秒秒表程​​序,但我注意到它比它應該的要慢; 那是數據似乎落后於實際時間。 下面看一下我的簡單代碼。 我假設控制台清除方法和/或延遲會減慢它的速度,但我不確定加快程序以獲得准確時間讀數的解決方案。

#include <chrono>
#include <thread>
#include <Windows.h>
#include <iostream>
#include <fstream>
using namespace std;
using namespace std::this_thread; // sleep_for, sleep_until
using namespace std::chrono; // nanoseconds, system_clock, 
seconds

void DELAY_IN_MILLISECONDS(int millisec) {
    sleep_until(system_clock::now() + milliseconds (millisec));
}
void clearConsole()
{
    system( "CLS");
}
struct Time {
    unsigned int tick = 0;
    unsigned int millisec = 0;
    unsigned int sec = 0;
    unsigned int min = 0;
    unsigned int hr = 0;
    unsigned int days = 0;
} timeAm;

int main()
{
    cout << "Started stopwatch" << endl;
    while (true)
    {
        //listens if user presses stop key
        //stop key is ESC
        //This should also write the time to a textFile

        if (GetKeyState(VK_ESCAPE) & 0x8000)
        {
            ofstream File("time.txt");
            File << "[" << timeAm.hr << " Hours] "
                 << "[" << timeAm.hr << " Minutes]"
                 << "[" << timeAm.min << " Seconds]"
                 << "[" << timeAm.sec << " Milliseconds]";
            File.close();
            return 0;
        }
        DELAY_IN_MILLISECONDS(1); //1 second delay
        //seconds
        timeAm.millisec++;
        //minutes
        if (timeAm.millisec > 59)
        {
            timeAm.millisec = 0;
            timeAm.sec++;
        }
        //hours
        if (timeAm.sec > 59)
        {
            timeAm.sec = 0;
            timeAm.min++;
        }
        //days
        if (timeAm.min > 23)
        {
            timeAm.min = 0;
            timeAm.hr++;
        }
        clearConsole(); //clears console
        //prints to console
        cout << "[" << timeAm.hr << " Hours] "
             << "[" << timeAm.hr << " Minutes]"
             << "[" << timeAm.min << " Seconds]"
             << "[" << timeAm.sec << " Milliseconds]";
    }
}

您的計時器做出了一些不正確的假設:

  1. (不正確)每次睡眠將精確到 1ms

    https://en.cppreference.com/w/cpp/thread/sleep_until中所述

    由於調度或資源爭用延遲,該函數也可能阻塞更長時間, until達到sleep_time之后。

  2. (不正確)所有其他代碼都立即執行(完全為零時間)。

    顯然這是一個瘋狂的想法。 但是你的代碼目前依賴它。 它會休眠 1ms(根據上面我們已經知道實際上可能不是 1ms),然后增加它的毫秒計數。 之后,它會進行一些計算和一些 I/O,然后再回到循環頂部以休眠另一個“1ms”。

    根據定義,如果睡眠之間的代碼需要任何時間,那么你的時鍾就會漂移。

  3. (不正確) system_clock是單調的

    文檔明確指出它不是(可以隨時調整時鍾)。 對於為這種事情設計的單調時鍾,請改用std::steady_clock

那么,您應該采取什么方法呢?

計時通常的工作方式是從time_point開始,然后在任何時候計算從那時到現在所經過的時間。 通過一些基本的數學運算,您可以將其轉換為HH:MM:SS.mmm

這樣做將處理前兩個不正確的假設。 每當您的進程喚醒時,您都可以計算真正的經過時間,而與其他代碼(或睡眠)花費的時間無關。

將所有內容滾動在一起,您可以執行以下操作:

#include <chrono>
#include <iomanip>
#include <iostream>
#include <thread>

int main()
{
    using std::chrono::duration_cast;
    using std::chrono::milliseconds;
    using Clock = std::chrono::steady_clock;

    std::cout << std::setfill('0');

    auto tbegin = Clock::now();
    unsigned long elapsedMilli = -1U;
   
    do {
        Clock::duration elapsed = Clock::now() - tbegin;
        unsigned long ms = duration_cast<milliseconds>(elapsed).count();
        if (elapsedMilli == ms)
        {
            std::this_thread::sleep_until(tbegin + milliseconds(ms + 1));
            continue;
        }
        elapsedMilli = ms;

        // Build time
        unsigned int t_millisec = ms % 1000; ms /= 1000;
        unsigned int t_sec = ms % 60; ms /= 60;
        unsigned int t_min = ms % 60; ms /= 60;
        unsigned int t_hr = ms % 24; ms /= 24;
        //unsigned int t_days = ms;

        // Display time
        std::cout << "["
             << std::setw(2) << t_hr << ":"
             << std::setw(2) << t_min << ":"
             << std::setw(2) << t_sec << "."
             << std::setw(3) << t_millisec << "]\n";

    } while (elapsedMilli < 5000);
}

現場演示: https ://godbolt.org/z/fzGbvx1sa

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM