C++ Builder XE4, 10.2 Tokyo > TTimer > 10秒ごとの処理 > 1. TTimer(1秒) + IncSecond(Now())での期限 | 2. TTimerのInterval指定 > 4分弱の間に1の結果に3秒程度のずれが見られる > 修正した
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)
処理内容
TTimerを使ったインターバル処理。
- TTimer(1秒) + IncSecond()での期限
- TTimerのみ使用
- Intervalプロパティに期限までの時間(msec)を指定
失敗編
実装
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TTimer *Timer1sec;
TTimer *TimerAlarm;
TButton *B_start;
TMemo *Memo1;
void __fastcall B_startClick(TObject *Sender);
void __fastcall Timer1secTimer(TObject *Sender);
void __fastcall TimerAlarmTimer(TObject *Sender);
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
static const int kWaitSecond = 10;
static TDateTime m_timeLimit;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Timer1sec->Enabled = false;
TimerAlarm->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_startClick(TObject *Sender)
{
// 1. 1sec timer
Timer1sec->Enabled = false;
Timer1sec->Interval = 1000; // msec
Timer1sec->Enabled = true;
m_timeLimit = IncSecond(Now(), kWaitSecond);
// 2. Alarm timer
TimerAlarm->Enabled = false;
TimerAlarm->Interval = kWaitSecond * 1000; // msec
TimerAlarm->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1secTimer(TObject *Sender)
{
if (Now() >= m_timeLimit) {
m_timeLimit = IncSecond(Now(), kWaitSecond);
Memo1->Lines->Add(L"1sec timer: " + Now().DateTimeString());
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerAlarmTimer(TObject *Sender)
{
Memo1->Lines->Add(L"alarm timer: " + Now().DateTimeString());
}
//---------------------------------------------------------------------------
結果
Memo1
alarm timer: 2017/10/17 19:16:44
1sec timer: 2017/10/17 19:16:45
alarm timer: 2017/10/17 19:16:54
1sec timer: 2017/10/17 19:16:55
alarm timer: 2017/10/17 19:17:04
1sec timer: 2017/10/17 19:17:05
alarm timer: 2017/10/17 19:17:15
1sec timer: 2017/10/17 19:17:15
alarm timer: 2017/10/17 19:17:25
1sec timer: 2017/10/17 19:17:25
alarm timer: 2017/10/17 19:17:35
1sec timer: 2017/10/17 19:17:35
alarm timer: 2017/10/17 19:17:45
1sec timer: 2017/10/17 19:17:45
alarm timer: 2017/10/17 19:17:55
1sec timer: 2017/10/17 19:17:56
alarm timer: 2017/10/17 19:18:05
1sec timer: 2017/10/17 19:18:06
alarm timer: 2017/10/17 19:18:15
1sec timer: 2017/10/17 19:18:16
alarm timer: 2017/10/17 19:18:25
1sec timer: 2017/10/17 19:18:26
alarm timer: 2017/10/17 19:18:35
1sec timer: 2017/10/17 19:18:36
alarm timer: 2017/10/17 19:18:45
1sec timer: 2017/10/17 19:18:46
alarm timer: 2017/10/17 19:18:55
1sec timer: 2017/10/17 19:18:56
alarm timer: 2017/10/17 19:19:05
1sec timer: 2017/10/17 19:19:07
alarm timer: 2017/10/17 19:19:15
1sec timer: 2017/10/17 19:19:17
alarm timer: 2017/10/17 19:19:25
1sec timer: 2017/10/17 19:19:27
alarm timer: 2017/10/17 19:19:35
1sec timer: 2017/10/17 19:19:37
alarm timer: 2017/10/17 19:19:45
1sec timer: 2017/10/17 19:19:47
alarm timer: 2017/10/17 19:19:55
1sec timer: 2017/10/17 19:19:57
alarm timer: 2017/10/17 19:20:05
1sec timer: 2017/10/17 19:20:07
alarm timer: 2017/10/17 19:20:15
1sec timer: 2017/10/17 19:20:18
alarm timer: 2017/10/17 19:20:25
1sec timer: 2017/10/17 19:20:28
- TTimer(1秒) + IncSecond()での期限
- => 4分弱で3秒のずれが見られた
- TTimerのみ使用
- Intervalプロパティに期限までの時間(msec)を指定
- => 4分弱で1秒以内のずれとなった
IncSecond()した時にmsec単位で誤差があるのだろうか?
1時間インターバル
alarm timer: 2017/10/17 20:35:03
1sec timer: 2017/10/17 20:35:04
alarm timer: 2017/10/17 21:35:03
1sec timer: 2017/10/17 21:35:04
alarm timer: 2017/10/17 22:35:03
1sec timer: 2017/10/17 22:35:05
alarm timer: 2017/10/17 23:35:03
1sec timer: 2017/10/17 23:35:06
alarm timer: 2017/10/18 0:35:03
1sec timer: 2017/10/18 0:35:07
alarm timer: 2017/10/18 1:35:03
1sec timer: 2017/10/18 1:35:08
alarm timer: 2017/10/18 2:35:03
1sec timer: 2017/10/18 2:35:08
alarm timer: 2017/10/18 3:35:03
1sec timer: 2017/10/18 3:35:09
alarm timer: 2017/10/18 4:35:03
1sec timer: 2017/10/18 4:35:10
alarm timer: 2017/10/18 5:35:03
1sec timer: 2017/10/18 5:35:10
alarm timer: 2017/10/18 6:35:03
1sec timer: 2017/10/18 6:35:11
alarm timer: 2017/10/18 7:35:03
1sec timer: 2017/10/18 7:35:12
やはり1sec timerの方でずれが発生している。
TTimer->Interval = 1000msecとはしているが、このインターバルには誤差が含まれる。その誤差が蓄積されて上記のようなずれが発生するのかもしれない。
11時間で8秒程度のずれ。11時間=39600秒。
8 / 39600 = 0.000202。
IncSecond()をNow()と組み合わせているのが問題である。
修正
IncSecond(Now())ではなく、IncSecond(timeLimit)とした。
こうすることで、TTimerのOnTimerコール時間の誤差とは関係なく期限を設定できる。
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
/*
v0.2 Oct. 18, 2017
- refactor: rename [m_timeLimit] to [s_timeLimit]
- fix bug: IncSecond() with Now() accumulated the deviation of the time
v0.1 Oct. 17, 2017
- add two timers
+ 1. TTimer(1sec) + time limit
+ 2. TTimer->Interval
*/
static const int kWaitSecond = 10; // 10
static TDateTime s_timeLimit;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Timer1sec->Enabled = false;
TimerAlarm->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::B_startClick(TObject *Sender)
{
// 1. 1sec timer
Timer1sec->Enabled = false;
Timer1sec->Interval = 1000; // msec
Timer1sec->Enabled = true;
s_timeLimit = IncSecond(Now(), kWaitSecond);
// 2. Alarm timer
TimerAlarm->Enabled = false;
TimerAlarm->Interval = kWaitSecond * 1000; // msec
TimerAlarm->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1secTimer(TObject *Sender)
{
if (Now() >= s_timeLimit) {
//m_timeLimit = IncSecond(Now(), kWaitSecond); // v0.1
s_timeLimit = IncSecond(s_timeLimit, kWaitSecond); // v0.2
Memo1->Lines->Add(L"1sec timer: " + Now().DateTimeString());
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerAlarmTimer(TObject *Sender)
{
Memo1->Lines->Add(L"alarm timer: " + Now().DateTimeString());
}
//---------------------------------------------------------------------------
alarm timer: 2017/10/18 8:49:39
1sec timer: 2017/10/18 8:49:39
alarm timer: 2017/10/18 8:49:49
1sec timer: 2017/10/18 8:49:49
alarm timer: 2017/10/18 8:49:59
1sec timer: 2017/10/18 8:49:59
alarm timer: 2017/10/18 8:50:09
1sec timer: 2017/10/18 8:50:09
alarm timer: 2017/10/18 8:50:19
1sec timer: 2017/10/18 8:50:19
alarm timer: 2017/10/18 8:50:29
1sec timer: 2017/10/18 8:50:29
alarm timer: 2017/10/18 8:50:39
1sec timer: 2017/10/18 8:50:39
alarm timer: 2017/10/18 8:50:49
1sec timer: 2017/10/18 8:50:49
alarm timer: 2017/10/18 8:50:59
1sec timer: 2017/10/18 8:50:59
alarm timer: 2017/10/18 8:51:09
1sec timer: 2017/10/18 8:51:09
alarm timer: 2017/10/18 8:51:19
1sec timer: 2017/10/18 8:51:19
alarm timer: 2017/10/18 8:51:29
1sec timer: 2017/10/18 8:51:29
alarm timer: 2017/10/18 8:51:39
1sec timer: 2017/10/18 8:51:39
alarm timer: 2017/10/18 8:51:49
1sec timer: 2017/10/18 8:51:49
1sec timer: 2017/10/18 8:51:59
alarm timer: 2017/10/18 8:51:59
alarm timer: 2017/10/18 8:52:09
1sec timer: 2017/10/18 8:52:09
alarm timer: 2017/10/18 8:52:19
1sec timer: 2017/10/18 8:52:19
alarm timer: 2017/10/18 8:52:29
1sec timer: 2017/10/18 8:52:29
alarm timer: 2017/10/18 8:52:39
1sec timer: 2017/10/18 8:52:39
alarm timer: 2017/10/18 8:52:49
1sec timer: 2017/10/18 8:52:49
alarm timer: 2017/10/18 8:52:59
1sec timer: 2017/10/18 8:52:59
1sec timer: 2017/10/18 8:53:09
alarm timer: 2017/10/18 8:53:09
alarm timer: 2017/10/18 8:53:19
1sec timer: 2017/10/18 8:53:19
alarm timer: 2017/10/18 8:53:29
1sec timer: 2017/10/18 8:53:29
alarm timer: 2017/10/18 8:53:39
1sec timer: 2017/10/18 8:53:39
ずれがなくなった。
疲れた頭でコーディングするとこういう失敗をする。
さらにstatic変数をm_定義している失敗も見つけたので修正しておいた。
Author And Source
この問題について(C++ Builder XE4, 10.2 Tokyo > TTimer > 10秒ごとの処理 > 1. TTimer(1秒) + IncSecond(Now())での期限 | 2. TTimerのInterval指定 > 4分弱の間に1の結果に3秒程度のずれが見られる > 修正した), 我々は、より多くの情報をここで見つけました https://qiita.com/7of9/items/94bdb9c8adc97b755e01著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .