Microsoft MVP성태의 닷넷 이야기
WaitHandle.WaitOne 과 Stopwatch에 관한 질문 [링크 복사], [링크+제목 복사],
조회: 17103
글쓴 사람
윤용한 (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)
976박성준6/13/201112852VS2008 Add-in 구현 관련 질문 [4]
972김길6/6/201114874메모리 해제 예외 처리 관련.. [2]
971강동원5/29/201112579firebird install건 [1]
970임동찬5/18/201113294ASP.net 솔루션 디버깅 관련 [1]
969이성환5/4/201115226WMI 를 사용하지 않고 하드웨어 정보를 가져올 수 없을까요? [3]
968김동미4/28/201114487안녕하세요 다시 한번 문의를 드립니다.. [2]파일 다운로드1
967임동찬4/22/201116950C# using문 관련 [9]
964김동미4/18/201114668wcf IsOneWay 속성관련 문의 입니다..
965정성태4/18/201115767    답변글 [답변]: wcf IsOneWay 속성관련 문의 입니다..
966김동미4/19/201114047        답변글 [답변]: [답변]: wcf IsOneWay 속성관련 문의 입니다.. [1]
963최재훈4/12/201112329wcf inactivityTimeout 설정시 문의 사항이 있습니다. [2]
962임동찬4/8/201112056TFS 사용관련 [1]
961임동찬4/7/201112413XSD & XML & XmlCodeGenerator [2]
960임동찬4/5/201113653XML Schema Editor [4]
959immm3/24/201111682로그인 연동 어려운 건가요? [1]
958꼭지3/3/201113312Supporting compressed request in WCF 3.5 [5]
957임동찬2/21/201113739WCF channel faulted 관련 [2]
956윤용한2/18/201117103WaitHandle.WaitOne 과 Stopwatch에 관한 질문 [3]
955최광욱2/17/201114294TFS 에서 소스 영구 제거 방법 [1]
954한장우2/16/201111938atl activeX 질문이요~ [1]
952박용운2/16/201112898IE8.0에서 BHO [1]
953박용운2/16/201112993    답변글 [답변]: IE8.0에서 BHO
951임동찬2/11/201112849WCF Service Reference [1]
950이성환2/9/201114152Windows application 프로젝트를 참조 했을 때 생성되는 실행파일을 직접 실행 불가능하도록 하고 싶습니다. [6]파일 다운로드1
947김순조1/24/201114168.NET based Com에서 Native ActiveX로 이벤트 보내기?? [2]파일 다운로드1
943김기룡1/3/201117231닷넷 에러시 조치사항관련... [2]
... 61  62  63  [64]  65  66  67  68  69  70  71  72  73  74  75  ...