0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++ Builder XE4, 10.2 Tokyo > TTimer > 10秒ごとの処理 > 1. TTimer(1秒) + IncSecond(Now())での期限 | 2. TTimerのInterval指定 > 4分弱の間に1の結果に3秒程度のずれが見られる > 修正した

Last updated at Posted at 2017-10-17
動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)

処理内容

TTimerを使ったインターバル処理。

  1. TTimer(1秒) + IncSecond()での期限
  2. TTimerのみ使用
    • Intervalプロパティに期限までの時間(msec)を指定

失敗編

実装

Unit1.h
//---------------------------------------------------------------------------

# 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
Unit1.cpp
//---------------------------------------------------------------------------

# 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
  1. TTimer(1秒) + IncSecond()での期限
    • => 4分弱で3秒のずれが見られた
  2. 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コール時間の誤差とは関係なく期限を設定できる。

Unit1.cpp
//---------------------------------------------------------------------------

# 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());
}
//---------------------------------------------------------------------------

run
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_定義している失敗も見つけたので修正しておいた。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?