Microsoft MVP성태의 닷넷 이야기
WaitHandle.WaitOne 과 Stopwatch에 관한 질문 [링크 복사], [링크+제목 복사],
조회: 17109
글쓴 사람
윤용한 (yonghany at gmail.com)
홈페이지
첨부 파일
 
(연관된 글이 2개 있습니다.)

안녕하세요.
Stopwatch와 WaitOne에 대해 질문드립니다.
개발환경은 .NET 4.0이고 TPL을 사용 중입니다.
문제는 다음과 같습니다.
task가 매 1분마다 한번씩 서버에 데이터를 보내는데
이게 정확히 1분마다 수행되는게 아니고 시간이 점점 짧아집니다.
System.Thread.Timer를 이용해도 마찬가지로 약간의 밀리세컨드 오차가 발생하여 정확히 1분만다 수행이 안됩니다. 실행시간이 짧으면 괞찮겠지만 최소 16시간에서 36시간 동안 진행되는 작업이라, 시간이 흐를수록 오차가 점점 커져가서 16시간 정도 되면 거의 1시간 가량이 단축되어 버립니다..--;

오차를 줄이기 위해 매분마다 하는 작업시간도 계산해서 frequency에서 뺀 시간만큼 wait를 해도 오차가 줄어들긴하지만 없어지지는 않네요.

제 생각에는 Stopwatch는 HighResolution으로 계산이 되지만 WaitOne
에서 부동소수점이 절삭되어서 계속해서 오차가 생기는 거 같은데 (맞나요?)...

이러한 오차없이 정확한 시간에 수행되도록 하는 방법이 있나요?


TimeSpan frequency = new TimeSpan(0,1,0);
for (int step=1; step<960; step++)
{
  Stopwatch stopwatch = Stopwatch.StartNew();

  Log.InfoFormat("STEP, {0}, {1:00}:{2:00}", step, (int)(CurrentStep / 60.0), CurrentStep % 60.0);

  //
  // 작업수행 (여기서 걸리는 시간은 길어야 00:00:00.0120852 입니다)
  //
  stopwatch.Stop();

  // 여기서 wait하는 시간은 큰 차이가 없습니다.
  // 대략 00:00:59.9901087 정도
  // 하지만 WaitOne이 좀도 빨리 깨어나는 거 같습니다.
  Log.DebugFormat("MEASURE, {0}, WAIT={1}", stopwatch.Elapsed, (Frequency - stopwatch.Elapsed));
  token.WaitHandle.WaitOne(frequency - stopwatch.Elapased);
}

수행결과 : millisecond가 약간씩 틀려짐

2011-02-18 11:05:11,602 [10] INFO STEP, 1, 00:01
2011-02-18 11:06:11,603 [10] INFO STEP, 2, 00:02
2011-02-18 11:07:11,602 [10] INFO STEP, 3, 00:03
2011-02-18 11:08:11,602 [10] INFO STEP, 4, 00:04
2011-02-18 11:09:11,601 [10] INFO STEP, 5, 00:05
2011-02-18 11:10:11,600 [10] INFO STEP, 6, 00:06
2011-02-18 11:11:11,600 [10] INFO STEP, 7, 00:07
2011-02-18 11:12:11,599 [10] INFO STEP, 8, 00:08
2011-02-18 11:13:11,599 [10] INFO STEP, 9, 00:09
2011-02-18 11:14:11,599 [10] INFO STEP, 10, 00:10
2011-02-18 11:15:11,599 [10] INFO STEP, 11, 00:11
2011-02-18 11:16:11,598 [10] INFO STEP, 12, 00:12
2011-02-18 11:17:11,597 [10] INFO STEP, 13, 00:13
2011-02-18 11:18:11,597 [10] INFO STEP, 14, 00:14
2011-02-18 11:19:11,596 [10] INFO STEP, 15, 00:15
2011-02-18 11:20:11,596 [10] INFO STEP, 16, 00:16
2011-02-18 11:21:11,595 [10] INFO STEP, 17, 00:17
2011-02-18 11:22:11,595 [10] INFO STEP, 18, 00:18
2011-02-18 11:23:11,594 [10] INFO STEP, 19, 00:19
2011-02-18 11:24:11,593 [10] INFO STEP, 20, 00:20
2011-02-18 11:25:11,593 [10] INFO STEP, 21, 00:21
2011-02-18 11:26:11,592 [10] INFO STEP, 22, 00:22
2011-02-18 11:27:11,592 [10] INFO STEP, 23, 00:23
2011-02-18 11:28:11,591 [10] INFO STEP, 24, 00:24
2011-02-18 11:29:11,591 [10] INFO STEP, 25, 00:25
2011-02-18 11:30:11,590 [10] INFO STEP, 26, 00:26
2011-02-18 11:31:11,590 [10] INFO STEP, 27, 00:27
2011-02-18 11:32:11,589 [10] INFO STEP, 28, 00:28
2011-02-18 11:33:11,588 [10] INFO STEP, 29, 00:29
2011-02-18 11:34:11,588 [10] INFO STEP, 30, 00:30
2011-02-18 11:35:11,587 [10] INFO STEP, 31, 00:31
2011-02-18 11:36:11,587 [10] INFO STEP, 32, 00:32
2011-02-18 11:37:11,586 [10] INFO STEP, 33, 00:33
2011-02-18 11:38:11,586 [10] INFO STEP, 34, 00:34
2011-02-18 11:39:11,585 [10] INFO STEP, 35, 00:35

시간측정값
2011-02-18 11:05:11,613 [10] DEBUG MEASURE, 00:00:00.0111593, WAIT=00:00:59.9888403
2011-02-18 11:06:11,615 [10] DEBUG MEASURE, 00:00:00.0129216, WAIT=00:00:59.9870780
2011-02-18 11:07:11,613 [10] DEBUG MEASURE, 00:00:00.0111803, WAIT=00:00:59.9888193
2011-02-18 11:08:11,614 [10] DEBUG MEASURE, 00:00:00.0120852, WAIT=00:00:59.9879144
2011-02-18 11:09:11,614 [10] DEBUG MEASURE, 00:00:00.0131108, WAIT=00:00:59.9868892
2011-02-18 11:10:11,608 [10] DEBUG MEASURE, 00:00:00.0079609, WAIT=00:00:59.9920387
2011-02-18 11:11:11,609 [10] DEBUG MEASURE, 00:00:00.0089334, WAIT=00:00:59.9910662
2011-02-18 11:12:11,608 [10] DEBUG MEASURE, 00:00:00.0089188, WAIT=00:00:59.9910804
2011-02-18 11:13:11,610 [10] DEBUG MEASURE, 00:00:00.0114450, WAIT=00:00:59.9885546
2011-02-18 11:14:11,608 [10] DEBUG MEASURE, 00:00:00.0090173, WAIT=00:00:59.9909823
2011-02-18 11:15:11,609 [10] DEBUG MEASURE, 00:00:00.0102548, WAIT=00:00:59.9897448
2011-02-18 11:16:11,609 [10] DEBUG MEASURE, 00:00:00.0111414, WAIT=00:00:59.9888582
2011-02-18 11:17:11,608 [10] DEBUG MEASURE, 00:00:00.0110511, WAIT=00:00:59.9889485
2011-02-18 11:18:11,609 [10] DEBUG MEASURE, 00:00:00.0120560, WAIT=00:00:59.9879436
2011-02-18 11:19:11,608 [10] DEBUG MEASURE, 00:00:00.0120682, WAIT=00:00:59.9879314
2011-02-18 11:20:11,604 [10] DEBUG MEASURE, 00:00:00.0086704, WAIT=00:00:59.9913292
2011-02-18 11:21:11,603 [10] DEBUG MEASURE, 00:00:00.0081886, WAIT=00:00:59.9918110
2011-02-18 11:22:11,604 [10] DEBUG MEASURE, 00:00:00.0089399, WAIT=00:00:59.9910593
2011-02-18 11:23:11,604 [10] DEBUG MEASURE, 00:00:00.0099999, WAIT=00:00:59.9899997
2011-02-18 11:24:11,603 [10] DEBUG MEASURE, 00:00:00.0100089, WAIT=00:00:59.9899907
2011-02-18 11:25:11,604 [10] DEBUG MEASURE, 00:00:00.0110559, WAIT=00:00:59.9889437
2011-02-18 11:26:11,603 [10] DEBUG MEASURE, 00:00:00.0110989, WAIT=00:00:59.9889007
2011-02-18 11:27:11,599 [10] DEBUG MEASURE, 00:00:00.0071067, WAIT=00:00:59.9928929
2011-02-18 11:28:11,603 [10] DEBUG MEASURE, 00:00:00.0121991, WAIT=00:00:59.9878001
2011-02-18 11:29:11,604 [10] DEBUG MEASURE, 00:00:00.0130569, WAIT=00:00:59.9869427
2011-02-18 11:30:11,599 [10] DEBUG MEASURE, 00:00:00.0090432, WAIT=00:00:59.9909564
2011-02-18 11:31:11,599 [10] DEBUG MEASURE, 00:00:00.0090979, WAIT=00:00:59.9909017
2011-02-18 11:32:11,599 [10] DEBUG MEASURE, 00:00:00.0100611, WAIT=00:00:59.9899385
2011-02-18 11:33:11,598 [10] DEBUG MEASURE, 00:00:00.0100315, WAIT=00:00:59.9899680
2011-02-18 11:34:11,599 [10] DEBUG MEASURE, 00:00:00.0111119, WAIT=00:00:59.9888877
2011-02-18 11:35:11,598 [10] DEBUG MEASURE, 00:00:00.0118449, WAIT=00:00:59.9881547
2011-02-18 11:36:11,599 [10] DEBUG MEASURE, 00:00:00.0121087, WAIT=00:00:59.9878909
2011-02-18 11:37:11,593 [10] DEBUG MEASURE, 00:00:00.0072878, WAIT=00:00:59.9927114
2011-02-18 11:38:11,594 [10] DEBUG MEASURE, 00:00:00.0079937, WAIT=00:00:59.9920059
2011-02-18 11:39:11,594 [10] DEBUG MEASURE, 00:00:00.0092098, WAIT=00:00:59.9907898
2011-02-18 11:40:11,593 [10] DEBUG MEASURE, 00:00:00.0091826, WAIT=00:00:59.9908170
2011-02-18 11:41:11,594 [10] DEBUG MEASURE, 00:00:00.0100944, WAIT=00:00:59.9899052
2011-02-18 11:42:11,593 [10] DEBUG MEASURE, 00:00:00.0099744, WAIT=00:00:59.9900252
2011-02-18 11:43:11,599 [10] DEBUG MEASURE, 00:00:00.0162488, WAIT=00:00:59.9837508
2011-02-18 11:44:11,593 [10] DEBUG MEASURE, 00:00:00.0110981, WAIT=00:00:59.9889015
2011-02-18 11:45:11,594 [10] DEBUG MEASURE, 00:00:00.0120811, WAIT=00:00:59.9879184
2011-02-18 11:46:11,594 [10] DEBUG MEASURE, 00:00:00.0130508, WAIT=00:00:59.9869488
2011-02-18 11:47:11,593 [10] DEBUG MEASURE, 00:00:00.0130893, WAIT=00:00:59.9869103
2011-02-18 11:48:11,589 [10] DEBUG MEASURE, 00:00:00.0090250, WAIT=00:00:59.9909750
2011-02-18 11:49:11,588 [10] DEBUG MEASURE, 00:00:00.0091449, WAIT=00:00:59.9908547
2011-02-18 11:50:11,589 [10] DEBUG MEASURE, 00:00:00.0101693, WAIT=00:00:59.9898307
2011-02-18 11:51:11,588 [10] DEBUG MEASURE, 00:00:00.0098909, WAIT=00:00:59.9901087
2011-02-18 11:52:11,589 [10] DEBUG MEASURE, 00:00:00.0110673, WAIT=00:00:59.9889323
2011-02-18 11:53:11,589 [10] DEBUG MEASURE, 00:00:00.0120986, WAIT=00:00:59.9879010



[연관 글]






[최초 등록일: ]
[최종 수정일: 2/18/2011]


비밀번호

댓글 작성자
 



2011-02-18 04시10분
윈도우 운영체제 자체가 RTOS가 아니다 보니, 정확한 시간 구현은 무리가 있을 것입니다. 어떻게 해서든 정밀도를 높이려면 스레드 우선순위를 높인다거나, 아예 DeviceDriver를 하나 제작해서 클록 인터럽트마다 정확하게 이벤트를 보내주는 것을 만들어야 할 것입니다. 그렇게까지 하는 것은 좀 어려울 것 같고. ^^

대신 중간 중간 현재의 시간값을 가지고 보정을 해줘야 하지 않을까 싶은데요. 검색해 보니.. 다음의 글 같은 것도 나오는군요.

C# timer synchronized with Datetime.Now
; http://stackoverflow.com/questions/2996236/c-timer-synchronized-with-datetime-now
정성태
2011-02-18 05시19분
[윤용한] 답변 감사합니다.
아무리 오차를 줄이려해도 0.000481 milliseconds 씩 계속해서 오차가 발생했었는데
검색하던 중에 multimedia timer를 이용한 글을 보고 적용해보니
99.999999% 정확하게 움직이고 있습니다^^.
가끔 0.000001 오차가 생기지만 그 다음 tick callback에서는 보정되어 정확하게 움직입니다.
16:12:15,735 [12] INFO STEP, 87, 01:27
16:13:15,736 [12] INFO STEP, 88, 01:28 *** 오차발생
16:14:15,735 [12] INFO STEP, 89, 01:29 *** 보정됨
16:15:15,735 [12] INFO STEP, 90, 01:30
16:16:15,735 [12] INFO STEP, 91, 01:31
16:17:15,735 [12] INFO STEP, 92, 01:32
16:18:15,735 [12] INFO STEP, 93, 01:33
16:19:15,735 [12] INFO STEP, 94, 01:34
16:20:15,735 [12] INFO STEP, 95, 01:35

The Multimedia Timer for the .NET Framework
http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx
[guest]
2011-02-20 09시57분
오~~~ 윤용한님 덕분에 새로운 것을 알았군요. ^^ 멀티미디어 타이머가 간간이 게임 프로그래머들 글에서 나오는 것을 읽긴 했었는데, 정확히 어떤 역할을 하는지는 모르고 있었습니다. 그 한 가지 예로 이해가 팍팍~~~ 되는군요. ^^ 너무 너무 감사드립니다. (오늘은 밥을 안 먹어도 배부를 것 같군요. ^^)
정성태

... 61  62  63  64  65  66  67  68  69  70  [71]  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
753신동열3/12/200811330비스타의 권한 상승 관련 질문 있습니다. [2]
751김재영3/6/200811008스레드와 비스레드간의 대기상태 순서에 대해 질문이 있습니다. [2]파일 다운로드1
752정성태3/7/200810501    답변글 [답변]: 스레드와 비스레드 간의 대기 상태 순서에 대해 질문이 있습니다. [1]
750김용현3/3/20089882스마트 클라이언트로 파일 다운로드시 파일의 크기가 0인 경우가 발생합니다. [2]
749임영한2/28/2008249602003서버에서 msxml3.dll 오류 "80070005" 문제입니다. [2]
748류재상2/27/200814512Remoting , Tcp Channel 사용시.. 외부에서 접근 보안문제... [3]
747한귀순2/20/200812922WinForm - DataGridView 소계 등 [3]
746박상영2/20/200810823리모팅 관련해서 [3]파일 다운로드1
745조승현2/20/200811677Response.Charset ANSI로 설정..하는부분이 어려워서요.. [1]
744오야2/5/200810136멤버십, 웹파트등의 생성테이블과 업무테이블간의 관계를 어떻게.. [2]
743김기룡1/29/200812212동일 이미지 판단 방법 관련 [2]파일 다운로드1
740경혜원1/28/200813683C#에서 이런게 가능 할런지요?
742정성태1/29/200811708    답변글 [답변]: C#에서 이런게 가능 할런지요? [1]
738임경훈1/25/200812577웹서비스에서 오라클DB에 연결할 때
741임경훈1/28/200812142    답변글 [답변]: 웹서비스에서 오라클DB에 연결할 때 [1]
737단테1/25/200813437안녕하세요 정성태님. C Run-time Library의 배포에 대해서 질문있습니다. [3]
736김현기1/24/200811385XML 접두어 포함한 XmlElement 작성법? [1]
735정명원1/9/200811208ActiveX 사용시 ... [2]
734제영한12/17/200711126웹서비스에서 사용자 정의 예외 사용하기 [2]
732김기룡12/3/200714020WebRequest 요청시 일본어 인코딩 관련 문의파일 다운로드1
733김기룡12/3/200710534    답변글 일어가 깨졌네요..테스트 문자 추가합니다.^^;;파일 다운로드1
739adnim1/27/200811566    답변글 [답변]: WebRequest 요청시 일본어 인코딩 관련 문의 [1]
731우기11/27/20079122[질문] clickonce 배포시 .net framework 2.0, 3.0 설치 시간 줄일 수 있는 묘수없을까요?? [1]
730김재영11/10/20079687스레드에 사용되는 함수에 값을 같이 넘기는 방법이 있습니까?? [2]파일 다운로드1
727제영한10/24/20079028시스템 설계에 대한 문의드립니다.
728정성태11/3/20079917    답변글 [답변]: 시스템 설계에 대한 문의드립니다. [2]
... 61  62  63  64  65  66  67  68  69  70  [71]  72  73  74  75  ...