BLOG main image
분류 전체보기 (66)
excel.101 (0)
rewind (9)
(3)
(2)
목공 (3)
(3)
me2day (0)
The Ethereal Void (9)
코드 (12)
귀찮은것 (0)
Black Friday Deals Uggs
Black Friday Deals Uggs
steamboat springs colorado lod..
steamboat springs colorado lod..
Looca의 생각
loocaworld's me2DAY
vervain의 생각
vervain's me2DAY
143,795 Visitors up to today!
Today 24 hit, Yesterday 32 hit
daisy rss
tistory 티스토리 가입하기!
2007.08.29 11:23
[System.Threading.Timer] 만약에 특정 시간에 어떠한 작업을 수행할려고 하면 어떻게 해야 될까? 기본적으로 프레임워크상에 Timer Class를 제공하기 때문에 우리는 그다지 크지 않은 노력을 통해 이를 사용할 수 있다. 하지만, 간혹 가다 이러한 Timer를 잘못 사용하는 경우가 있다.

서두에 밝힌 것처럼 매일 "오전 09:00"에 특정 작업을 수행하고 싶다고 할 경우, 어떠한 사람들은 Timer를 사용하여 매 초, 혹은 일정 주기 간격으로 시간을 확인하는 작업을 수행하여 현재 시간과 특정 작업이 일어나야 될 시간을 비교하여 시간이 지났거나, 같을 경우 작업을 실행한다. 하지만 이는 낭비이다. 유저에게 특정 간격으로 Notify를 줄 필요성이 없다면 굳이, 주기적인 Timer를 다시 주기적으로 실행되도록 할 필요는 없다. 이는 꼭 "역전"이라고 표기해야 될 것을 "역전앞"이라고 표기하는 것과 마찬가지이다.

이러한 "낭비"를 없애기 위한 간단한 방법은 간단하게 dueTime을 계산해 주는 방법이 있다.

현재 시간이 09:00이고 특정 작업이 실행되어야 할 시간이 10:00라면 1시간을 dueTime으로 넣어주면 원하는 시간에 특정작업이 한번 실행된다. 만약 24시간 주기로 특정 시간에 특정 작업을 해야 된다면, Timer의 실행 주기를 24시간을 넣어주면 된다.

public delegate void stCallBackDelegate();

    public class ScheduledTimer
    {
        private Timer _timer;

        public ScheduledTimer() { }

        public static TimeSpan GetDueTime(TimeSpan A, TimeSpan B)
        {
            if (A < B)
            {
                return B.Subtract(A);
            }
            else
            {
                return new TimeSpan(24, 0, 0).Subtract(B.Subtract(A));
            }
        }

        public void SetTime(TimeSpan _time, stCallBackDelegate callback)
        {
            if (this._timer != null)
            {
                // Change 매서드 사용 가능.
                this._timer.Dispose();
            }

            TimeSpan Now = DateTime.Now.TimeOfDay;
            TimeSpan DueTime = GetDueTime(Now, _time);
 
            this._timer = new Timer(new TimerCallback(delegate(object _callback)
            {
                ((stCallBackDelegate)_callback)();
            }), callback, DueTime, new TimeSpan(24, 0, 0));
          }
    }
기본적으로 TimeSpan 클래스는 "시간의 길이"를 나타낸다. 즉 9시간에 24시간을 더하면 33시간, 1일 9시간이 된다. DateTime.Now.TimeOfDay는 해당 날짜의 0시부터 현재 시간까지의 길이를 돌려준다. 즉 TimeSpan 클래스를 사용하면서 착각해서는 안되는 부분은 9시간에 24시간을 더하면 24시간 주기로 다시 9시가 될 것이라는 생각이다. 우리가 원하는 스캐쥴러는 이러한 방식이 필요하다. 즉 현재 시간이 오전 11시이고, 특정 작업이 실행되어야 할 시간이 이미 지난 시간이 오전 9시라면, 지연되어야 할 시간은 22시간이다.

작업 예약 시간이 현재 시간보다 나중이면 간단하게 현재 시간에서 예약 시간을 빼면 지연되어야 할 시간이 계산된다. 하지만 반대로 예약 시간이 이미 지난 시간이면, 마이너스 시간 길이가 나오는데, 이를 dueTime에 넣어주면 Timer는 Disable상태가 되어 버린다. 고로 위와 같은 방법으로 지연시간을 계산하여야 한다.
신고
BlogIcon 도아 | 2007.10.08 11:00 신고 | PERMALINK | EDIT/DEL | REPLY
제 블로그에 답글을 달아 주신 분들(http://offree.net/entry/Greetings-Reply )을 순회하고 있습니다. 소중한 댓글 감사합니다.

그런데 주 관심사가 프로그래미인 것 같습니다.
BlogIcon slimes | 2007.11.05 11:33 신고 | PERMALINK | EDIT/DEL | REPLY
네.. :) 관심사는 아니고 업에 가깝습니다.
go2by | 2009.02.18 10:14 신고 | PERMALINK | EDIT/DEL | REPLY
좋은 글 감사합니다.
덕분에 제가 하려는 작업을 쉽게 끝낼 수 있었네요..

그런데 위 함수 GetDueTime에서 잘못된 부분이 있는 듯 하여 글 남깁니다.
A > B 일 경우,
return new TimeSpan(24, 0, 0).Subtract(A.Subtract(B)); 가 맞지 않나요?
B.Subtract(A)의 결과는 음수이고 그 앞의 Subtract와 만나게 되면 결국 24시간을 "더하게" 될텐데요..
예를 들어, 현재 시각이 09시 이고 작업시각이 매일 02시라면,
기존 식으로는 1.07의 결과값이 나오므로 아마도 최초 작업시각은 다음날 16시가 될 것입니다.
하지만 제가 말씀드린 식으로 처리하면 17의 결과값이 나오므로 원하는 시각에 작업이 시작되겠죠..
BlogIcon 엔돌슨 | 2009.06.06 10:35 신고 | PERMALINK | EDIT/DEL | REPLY
this._timer = new System.Windows.Forms.Timer(new TimerCallback(delegate(object _callback)
코드의 일부중 이게 맞나요?
모호하다고해서 선언을했는 데요..

이런 알고리즘이 필요한데 이해는 대략되는 데 소스 보고도 구현이 안되네요.
컴파일지 오류가나요.

오류 1 '4'개의 인수를 사용하는 'Timer' 메서드에 대한 오버로드가 없습니다.

아마도 모호한거 때문에 그런거 같아서 변경을 했는 데 오버로드 오류가 나네요..
BlogIcon 엔돌슨 | 2009.06.06 11:46 신고 | PERMALINK | EDIT/DEL | REPLY
using System.Threading; 를 사용하니 되네요 몰랐습니다 ^^
| 2009.06.06 12:57 | PERMALINK | EDIT/DEL | REPLY
비밀댓글입니다
BlogIcon slimes | 2009.06.21 22:39 신고 | PERMALINK | EDIT/DEL
시간 길이는 TimeSpan으로 지정해 주시면 됩니다. (#21)
그리고 두번째 인자로 callback 함수에 대한 대리자를 지정해 주시면 되는데, 소스 #01 라인에 보시면 아시겠지만, stCallBackDelegate는 인자가 없는 delegate입니다.

public void _callback() {
지정 시간이 지난 뒤 처리될 작업
}..

new stCallBackDelegate(_callback) 이렇게 넣어주시면 되겠습니다.
nanumoku | 2013.01.08 19:22 신고 | PERMALINK | EDIT/DEL | REPLY
#17에

return new TimeSpan(24, 0, 0).Subtract(A.Subtract(B));

이게 맞을 듯 한데....
kuroko314 | 2013.03.28 11:05 신고 | PERMALINK | EDIT/DEL | REPLY
돌려보니 17 번째 라인
return new TimeSpan(24, 0, 0).Subtract(B.Subtract(A));

return new TimeSpan(24, 0, 0).Subtract(A.Subtract(B));
이렇게 바뀌어야 맞네요
Name
Password
Homepage
Secret

티스토리 툴바