Microsoft MVP성태의 닷넷 이야기
WaitHandle.WaitOne 과 Stopwatch에 관한 질문 [링크 복사], [링크+제목 복사]
조회: 17055
글쓴 사람
윤용한 (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)
1091김대경9/20/201210505    답변글 [답변]: windows2008 에서 ActiveX 사용 시 문제점. [2]파일 다운로드1
1081Seon...8/20/201212846WCF 파일 업,다운로드 문제 [2]
1080배동선8/13/201211665정품 라이센스 인증 개발에 대해 조언을 구하고 싶습니다 [4]
1079송준호8/11/20129633basicHttpBinding stream 전송에 관하여 질문드립니다. [1]
1078Ho S...8/10/20128822윈도우폰 지도 구현에서 ㅠㅠㅠ 질문드립니다. [1]파일 다운로드1
1077한우주8/6/201211766웹서비스 호출 후 세션 유지하기 [1]
1076이성환8/2/201211240dynamic 변수 할당은 도대체 어디에???? [1]
1073pass...7/24/201211084c# 으로 만드는 음성인식/TTS 프로그램에 관련해서.. [3]
1072일반인7/23/201213352rss 만드는 방법 알려주실 수 있으신가요? [5]
1069임경훈7/20/201214068아래와 같은 오류후 IIS가 다운되는 현상이 발생합니다. [1]
1068신호철6/15/201213417ClassLibrary COM+ 등록 안되는 현상 [2]
1067김은주6/14/201222790소스세이프 사용시 pfx 파일 빌드 실패 [3]
1066너무초보6/3/20129978안녕하세요! 디렉토리 삭제 오류 질문 좀 드립니다. [4]
1065이성환5/23/201211763Assembly.LoadFrom Assembly.Load 의 차이점이 궁금합니다. [2]파일 다운로드1
1064푸우5/21/201210569GPU 디바이스 재시작시 WPF + .NET 3.5 기반 어플리케이션 UI 문제 [2]
1063발코더5/20/201210729귀신 곡할 상황 질문입니다. [3]
1062김규덕5/12/201210861ffmpeg 관련 조언 구합니다. [2]
1061Dave5/11/20129591언제 스크린 캡쳐 하시나요? [1]
1058정재훈5/11/201211483c#으로 동영상에 로고를 삽입하는 기능을 구현중입니다. [3]
1057전남진5/1/201210556** 몇일째 고생하다가 웹 검색을 통해 알게되어 질문드립니다.. 초보 질문이긴하지만 도움 부탁드려요 [2]
1056안현수5/1/201212295listview 와 웹파싱에관해 질문드립니다 [1]파일 다운로드1
1055이성환4/30/201210453WPF FramworkElement의 이벤트를 가져오고 싶습니다. [3]
1054정웅모4/20/20129978안녕하세요 [1]
1053폭풍코딩4/19/201210319스마트클라이언트 ctrl-c 복사가 작동하지 않습니다. [1]
1052에슈리온4/17/201226028ClickOnce 배포시 클라이언트의 설치경로를 지정할 수 없나요? [1]
1051최정수4/10/201213154WCF 클라이언트 비정상 종료 관련 [1]
... [61]  62  63  64  65  66  67  68  69  70  71  72  73  74  75  ...