타이머 이벤트라고 하는 것은 IDL에서 어떤 작업을 일정 시간의 주기를 갖고 반복적으로 수행하기 위하여 필요한 방법을 뜻합니다. 예를 들면, 요이땅하고 시간을 측정하기 시작하여 일정 시간이 경과한 순간 어떤 작업을 하도록 하는 경우도 있을 수 있고, 시간에 따라 변하는 데이터를 주기적으로 자동으로(1분에 한번씩이라든지) 데이터를 수신하여 처리하는 작업 등도 이러한 경우에 해당될텐데요. 물론 IDL에서는 예전부터 이러한 타이머 기반의 처리가 가능은 했었습니다. 다만, 과거의 방법을 사용하려면 GUI 프로그래밍(IDL에서는 Widget 프로그래밍이라고도 합니다)의 기본은 어느 정도 알아야 했습니다. 간단하게라도 GUI가 존재하는 상태에서만 타이머 이벤트의 생성이 가능했기 때문입니다. 더구나 이 방법은 리눅스나 유닉스와 같은 OS에서는 XWindow 기반에서만 사용이 가능하기 때문에, 작업의 특성상 XWindow 환경을 사용하지 않아야 하는 상황에서는 아예 GUI 기반의 타이머 생성 기법 자체를 사용하지 못하는 경우들도 있었습니다. 게다가 GUI 프로그래밍에 익숙하지 않은 일반 유저들 입장에서 그리 쉽게 접근하기는 어려운 측면도 분명히 있었습니다. 여러가지 제약사항들이 많았던 셈이지요. 그래서 IDL 기반으로 작업하는 프로그램을 sav 실행파일로 하나 만들어놓고, 리눅스같은 시스템에서 크론탭(cron tab) 등의 방법을 사용하여 일정 시간 주기로 작업을 수행하도록 하는 다소 복잡한 방식을 이용하는 경우가 많았습니다.
그런데 IDL 8.3 버전부터는 TIMER라고 하는 객체 클래스가 새로 도입이 되어서, 예전처럼 굳이 이것저것 복잡한 상황들을 고려하지 않고도 타이머 이벤트의 사용이 매우 간편해졌습니다. 물론 "객체 클래스"라는 용어가 두려운 유저들도 있을 수 있겠지만, 아래에 소개될 예제코드를 보면 별로 대단한 것도 아닙니다. 일단 타이머 이벤트를 생성하는 기본적인 문구는 다음과 같습니다.
id = TIMER.Set(2., 'handle_timer_event', userdata)
여기서 id는 그냥 이벤트 자체의 인식표같은 것으로 보면 됩니다. 그리고 TIMER.Set 안쪽에 처음 등장하는 항목(여기서는 2.)은 시간 딜레이를 초 단위로 나타낸 값입니다. 즉 지금부터 2.0초 후에 이벤트를 발생시키라는 의미입니다. 그리고 따옴표 안에 있는 것은 이벤트 처리를 담당할 루틴의 이름입니다. 이러한 이름을 가진 프로그램이 어디엔가 있어야만 하겠지요. 그리고 마지막 항목인 userdata라는 것은 이벤트 처리루틴으로 전달하고 싶은 값에 해당됩니다. 이 내용은 작업의 성격에 따라 달라질겁니다. 이와 같은 방법을 기반으로 하여 타이머 이벤트를 발생시키고, 그 이벤트가 발생한 시점의 시각을 출력하는 간단한 예제 프로그램을 만들어보면 아래와 같습니다.
PRO handle_timer_event, id, userdata
n = userdata+1
PRINT, 'Timer executed at ', SYSTIME(), n
END
PRO test_timer_83
n = 0
id = TIMER.Set(2., 'handle_timer_event', n)
END
위의 내용을 test_timer_83.pro라는 파일로 저장하고 컴파일 및 실행을 하면, 실행 직후 2초 후에 'Timer executed ...'와 같은 문구가 출력됩니다. 여기서는 타이머 이벤트가 발생한 순간의 시각을 출력하도록 한 경우입니다. 그런데 이 프로그램을 실행해보면 시작 후 2초 후에 이벤트가 한번 실행되고는 그냥 끝납니다. 사실 이렇게만 해놓으면 단발성 이벤트 한번만 발생하고 끝납니다. 그렇다면, 그 이후에도 계속 2초마다 이벤트가 발생하도록 하려면 어떻게 해야 할까요? 이 경우에는 원래 타이머 이벤트를 생성했던 문구와 똑같은 내용을 타이머 이벤트 처리 루틴안에 한번 더 넣어주면 됩니다. 그러면 내용은 다음과 같이 됩니다.
PRO handle_timer_event, id, userdata
n = userdata+1
PRINT, 'Timer executed at ', SYSTIME(), n
id = TIMER.Set(2., 'handle_timer_event', n)
END
PRO test_timer_83
n = 0
id = TIMER.Set(2., 'handle_timer_event', n)
END
이렇게 수정된 프로그램을 실행하면, 시작 후 계속 2초 주기로 이벤트가 발생하는 것을 확인할 수 있습니다. 그런데 이번에는 또 다른 문제가 생기는데요. 바로 끝이 안난다는 문제입니다. 그냥 두면 계속 갑니다. 그래서 '정지' 버튼을 누르던가 아니면 IDL을 아예 꺼버리지 않는 한은 이벤트가 계속 이어진다는 특성이 있습니다. 물론 작업의 성격에 따라서는 이렇게 충직하게 계속 임무를 수행해야 할 경우도 있겠지만, 그렇지 않고 어떤 조건에 부합되면 알아서 타이머를 정지하도록 하는 것도 가능은 합니다. 사실 이 예제 프로그램에서 userdata의 자리에서 n이라는 변수를 도입한 것도 이러한 이유 때문입니다. 이번엔 위 프로그램을 아래와 같이 수정해봅시다.
PRO handle_timer_event, id, userdata
n = userdata+1
PRINT, 'Timer executed at ', SYSTIME(), n
IF n EQ 5 THEN BEGIN
result = TIMER.Cancel(id)
PRINT, 'Timer Cancelled'
ENDIF ELSE $
id = TIMER.Set(2., 'handle_timer_event', n)
END
PRO test_timer_83
n = 0
id = TIMER.Set(2., 'handle_timer_event', n)
END
이렇게 수정된 프로그램을 실행하면, 시작 후 2초 주기로 이벤트가 발생하다가 5회차가 되는 순간 이벤트는 종료됩니다. 타이머의 종료는 TIMER 클래스의 Cancel이라는 메서드를 사용하면 됩니다. 그 외에도 TIMER 클래스에서 사용 가능한 다른 메서드들도 좀 있는데, 세부 내용은 IDL 도움말에서 찾을 수 있습니다. 어쨌든 중요한 것은 굳이 GUI를 띄워놓지 않고도 일반적인 IDL 작업들을 타이머 기반으로 수행할 수 있는 좀 더 간편한 방법이 8.3에서 도입이 되었다는 사실입니다.
참고로 이 내용은 최근에 IDL Datapoint 블로그에 올라온 내용(원문링크) 및 IDL 도움말을 참조하여 작성되었음을 밝혀둡니다.
'IDL > Miscellaneous' 카테고리의 다른 글
특정 문구를 포함하는 IDL 루틴을 찾아주는 프로그램 소개 (0) | 2014.07.24 |
---|---|
IDL 기본교육 잘 마쳤습니다 (사진 포함) (0) | 2014.05.30 |
IDL의 처리속도 테스트 (2) | 2014.05.02 |
한국의 태양활동 분석기술을 미국 NASA에 제공! (0) | 2013.12.05 |
!CONST로 과학기술 분야의 다양한 상수들을 사용해봅시다 (0) | 2013.10.07 |