쓰레드가 고속으로 돌 때 어떤 값을 화면에 표시한다면
1초당 적당한 횟수를 표시를 하는 것이 좋습니다.
지나치게 빨리 많이 표시한다고 화면에 다 보이는 것도 아니고,
일정 프레임을 넘어가면 사람이 인지하는 한도를 넘어가기 때문에,
CPU 낭비해가며 표시할 필요는 없습니다.
쓰레드가 돌 때 특히 중요한 것이 바로 일정시간 마다, 사람이 보기에 매우 자연스럽게
화면이 갱신되는 것인데, 대략 TV나 영화가 화면을 갱신하는 것에 기준하는 것이 좋지 않나 생각됩니다.
그래서 1초에 영화는 24프레임, TV는 30프레임 갱신되므로,
대략 1초(1000 Milliseconds)에 25회~30회 정도 갱신하면 매우 자연스럽게 됩니다.
(물론 전문 동영상 화면의 갱신이라면 1초에 60회 갱신 등을 고려해야 보다 자연스러워 집니다)
이건 보통의 동영상일 경우고 숫자나 메시지를 갱신할 때는 보다 프레임을 낮추어도 상관이 없습니다.
쓰레드에서 적당히 갱신 횟수를 조절하는 방법으로는 아래 예제를 만들었는데 이러한 방법이 일반성이 있을 것 같군요.
하나는 함수를 써서 시간을 체크하는 방법이고, 또 하나는 직접 계산하는 방법인데,
둘다 DateUtils.hpp의 MilliSecondsBetween 함수를 사용해 매우 간편하게 시간차를 구합니다.
이는 매우 정밀한 8바이트 TDateTime 형 클래스를 사용하기 때문에 안심하고 사용할 수 있습니다.
보통 시간차를 구하는 방법으로 많이 쓰이는 것이 GetTickCount인데
GetTickCount는 DWORD로 4바이트 밀리세커 카운트를 돌립니다.
4바이트형이니 값이 마지막까지 차면 다시 0으로 돌아오게 됩니다.
그러므로 이를 그대로 가지고 시간차 계산을 해도 아무런 문제는 없습니다.
현재카운트 - 이전카운트 값 형태에서는 다시 카운트가 0을 지나 값이 올라가도
이상없이 그 시간차가 잘 구해집니다.
하지만 GetTickCount는 정밀도가 떨어진다고 알려져 있습니다.
TDateTime 형은 시간에서 바로 가져오므로 가져오는 순간의 값은 매우 정확하다고 볼수 있으나,
GetTickCount에서 가져오는 값은 시스템의 상황에 따라 오차가 발생한다고 합니다.
GetTickCount는 4바이트 값이라 49일즈음에는 증가되는 값이 한계에 도달해 다시 처음부터 다시 시작하게 됩니다.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
// 테스트 쓰레드
class CThread : public TThread
{
private:
// 함수로 일정 시간이 지났나 체크.
//
bool IsTimeBetween(int interval, TTime& old_time)
{
TTime now = Now();
if (MilliSecondsBetween(now, old_time) >= interval)
{
old_time = now;
return true;
}
return false;
}
protected:
TTime Current;
int Count;
int CountMilli40;
void __fastcall Execute()
{
while(!Terminated)
{
// 40밀리초 마다 화면 갱신하기. 1초에 화면 표시 25번 갱신.
// 100밀리초 마다 화면 갱신하기. 1초에 화면 표시 10번 갱신.
//
#if 1
if (IsTimeBetween(40, Current))
{
CountMilli40++;
Synchronize(Display);
}
#else
// 직접 체크.
TTime now = Now();
if (MilliSecondsBetween(now, Current) >= 40)
{
Current = now;
CountMilli40++;
Synchronize(Display);
}
#endif
else
{
Count++;
Sleep(20);
}
}
}
public:
__fastcall CThread(bool CreateSuspended) : TThread(CreateSuspended)
{
FreeOnTerminate = true;
Count = 0;
CountMilli40 = 0;
Current = Now();
}
void __fastcall Display()
{
String s;
s.printf("Current Count: %d Count2: %d", CountMilli40, Count);
Form1->Label1->Caption = s;
}
};
void __fastcall TForm1::FormCreate(TObject *Sender)
{
CThread *a = new CThread(false);
a;
}
//---------------------------------------------------------------------------
|
해서 합니다. 그러면 event가 set이 되지 않는다면 time_msec동안 있다가 timeout되어서 다음을 실행합니다.
요즘 만드는 프로그램은 한 프로그램안에 플러그인 dll과 그 안에 쓰레드들이랑 엄청 돌아갑니다. 다행히 동기화나 소멸할때등 여러가지 문제점들을 해결하니 프로그램이 정말 부드러워지네요. cpu 점유율도 거의 0~10%안팍이구요.