"for loop실행 중 Timer Event가 제대로 작동하나요?"

for loop가 약 30분 정도 돌아가야 되는데(기계제어 프로그램이기 때문에 for loop내에서 여러조건이 만족되어야 for loop내에서 다음 단계(step)로 넘어감) 이 과정중에 Timer Event를 사용할 필요가 있습니다. 즉 For Loop내에서 단계(step)가 진행될 때마다 global Variable이 변하게 되는데 이 때 이벤트를 걸어 다른 작업(Com2 Port를 통해 순간적으로 수신/전송을 해야 됨)을 해야 되기 때문이거든요. 그런데 for loop내에서 이 다른작업이라는 놈을 넣어니 최초 한번만 실행 되고 그 이후에는 반응이 없더라구요. 그래서 Timer event를 이용하여 일정간격으로 이 다른작업이라는 놈을 실행되도록 했더니 되긴 되는데 제대로 되지 않더군요. 즉 Global Variable은 계속 바뀌는데 Timer Event 함수내에서 이 Global 변수를 추적해 보니까 Timer함수내로 이 변수가 제대로 넘어오지 않더군요. (이하생략)


>> 답변 : 지나가는사람 님 ( bcbdn C++Builder Q&A 14815번 )

Timer의 경우는 그런상태가 벌어지는 경우가 많습니다.
저도 비슷한 문제로 여러가지로 테스트를 해보았는데...
윈98 계열의 경우는 그러한 상태가 일어나는 경우가 상당히 많고.. NT 계열은 그나마 좀 낮습니다.
(98은 마우스로 캡션바를 드래그 & 드롭하는 경우에도 Timer는 멈춥니다.)
그렇지만.. NT라도 제대로 제어를 하기 위해서는 스레드는 필수입니다.

>> 추가 : for loop나 while문을 계속 돌리고 싶은 경우 빠져나오는 조건이 명확하지 않다면 Thread를 쓰시는 편이 시스템 전체가 다운되는 현상을 방지할 수 있습니다.
Thread는 File > New > Thread Object 이러한 과정을 생성하면 되구요. 예를 들면 아래와 같이 생성할 수도 있습니다.

>> 참고

@ Execute
쓰레드 실행시에 실행 코드를 가지기 위한 순수 가상 메쏘드를 제공한다
(원형) virtual void __fastcall Execute(void) = 0;
(상세) 쓰레드 실행시 실행되어질 코드의 포함하고 실행하기위해 쓰인다. 이곳에서 쓰레드를 빠져나갈 조건을 체크한다.
CreateSuspended = false 라면 Create, CreateSuspended = true 라면 쓰레드를 생성 후에
Resume이 호출되었을 때 쓰레드는 실행한다.

(주의) 다른 오브젝트의 properties와 methods에서 직접적으로 쓰레드의 Execute를 사용하지 말라. 대신, procedure를 나눠서 Synchronize 메쏘드의 인자로써 procedure를 사용하라.


@ Synchronize
주요 VCL 쓰레드 호출 Executes method

(원형) typedef void __fastcall (__closure *TThreadMethod)(void);
       void __fastcall Synchronize(TThreadMethod &Method);

(상 세) Synchronize는 주 VCL 쓰레드를 사용하기위해 실행되어지는 메쏘드에만 호출되어야하기 때문에, 멀티-쓰레드에는 사용되지 말아야 한다. 쓰레드 호출이 안전할지 확실하지 않다면, 주 VCL 쓰레드를 거쳐서 Synchronize 메쏘드를 호출해라.
Execution 쓰레드는 주 VCL 쓰레드안에서 메쏘드가 실행될 동안에는 정지되어 있다.
(주의) critical section이나 multi-read exclusive-write synchronizer에서 사용되는 불안정한 메쏘드를 보호할 수 있다.

@ Priority
쓰레드 프로세스에서 상대적인 스케줄링 우선순위
(원형) enum TThreadPriority {tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical};
       __property TThreadPriority Priority = {read=GetPriority, write=SetPriority,nodefault};

(상세) Priority는 쓰레드 스케줄링시에 사용되는 우선순위이다.
TThreadPriority형은 아래에 정의된 표에 따라 TThread 콤포넌트의 Priority property 값을 정의한다. Windows 우선순위 스케일에 기준으로 각 쓰레드의 CPU cycle을 스케쥴한다.

값                       내용

tpIdle                  시스템이 idle 상태일때만 실행된다. tpIdle의 우선순위를 가진  쓰레드의 실행때문에 다른 쓰레드 프로세스를 interrupt 하지는 않을 것이다.
tpLowest                  normal보다 2 point 낮은 우선순위를 가진다.
tpLower                  normal보다 1 point 낮은 우선순위를 가진다.
tpNormal                  normal 우선순위이다.
tpHigher                  normal보다 1 point 높은 우선순위를 가진다.
tpHighest                  normal보다 2 point 높은 우선순위를 가진다.
tpTimeCritical         최고 높은 우선순위를 가진다.

주 의 : CPU 점유율이 높은 operation의 우선순위를 높이는 것은 동일 Application내에 타 쓰레드 가 동작하지 못하게 할 수도 있다. External event를 기다리는데 대부분의 시간을 사용하는 쓰레드의 우선순위를 높여라.


@ WaitFor

쓰레드를 종료되기를 기다리고,  종료시 ReturnValue property를 return한다.

(원형) int __fastcall WaitFor(void);

(상 세)  WaitFor를 호출하면 쓰레드 종료 시 ReturnValue를 얻을 수 있다. WaitFor는  Execute 메쏘드가 끝나거나 Terminated property = true 가 되어 빠져나와서 쓰레드가 종료될때까지 return되지 않는다.

--------------------------------------------------------------------------------------------------

이번에 BDS 2006으로 바뀌면서 몇가지 바뀐것이 있는데요,
그중 하나가 Synchronize의 사용법 입니다. 저는 이걸 몰라서 몇일동안 고생해서
외국의 포럼에서 찾은 내용 팁란에 올립니다.

기존에는
void __fastcall CTEST::Test()

라는 메소드를 동기화 시키려면
Synchronize(Test);
라고만 쓰면 됬는데 새롭게 바뀐 문법에서는

Synchronize(&Test);

이렇게 쓰셔야 에러 안납니다.

------------ 볼랜드포럼에서 발췌 ---------------------------------------

+ Recent posts